* Add support for Haiku OS * Adjust DISTFILES and dist rule in haikumaster
@@ -1,4 +1,4 @@ | |||
VERSION = 2.8.1 | |||
include VERSION.mk | |||
PREFIX ?= /usr/local | |||
MANPREFIX ?= $(PREFIX)/share/man | |||
@@ -57,7 +57,7 @@ CFLAGS += $(CFLAGS_CURSES) | |||
LDLIBS += $(LDLIBS_CURSES) | |||
DISTFILES = src nnn.1 Makefile README.md LICENSE | |||
DISTFILES = src nnn.1 Makefile README.md LICENSE VERSION.mk | |||
SRC = src/nnn.c | |||
HEADERS = src/nnn.h | |||
BIN = nnn | |||
@@ -0,0 +1 @@ | |||
VERSION = 2.8.1 |
@@ -0,0 +1,117 @@ | |||
include VERSION.mk | |||
PREFIX ?= /boot/system/non-packaged | |||
MANPREFIX ?= /boot/system/non-packaged/documentation/man | |||
STRIP ?= strip | |||
PKG_CONFIG ?= pkg-config | |||
INSTALL ?= install | |||
CP ?= cp | |||
CFLAGS_OPTIMIZATION ?= -O3 | |||
O_DEBUG := 0 | |||
O_NORL := 0 # no readline support | |||
O_NOLOC := 0 # no locale support | |||
# convert targets to flags for backwards compatibility | |||
ifneq ($(filter debug,$(MAKECMDGOALS)),) | |||
O_DEBUG := 1 | |||
endif | |||
ifneq ($(filter norl,$(MAKECMDGOALS)),) | |||
O_NORL := 1 | |||
endif | |||
ifneq ($(filter noloc,$(MAKECMDGOALS)),) | |||
O_NORL := 1 | |||
O_NOLOC := 1 | |||
endif | |||
ifeq ($(O_DEBUG),1) | |||
CPPFLAGS += -DDBGMODE | |||
CFLAGS += -g | |||
LDLIBS += -lrt | |||
endif | |||
ifeq ($(O_NORL),1) | |||
CPPFLAGS += -DNORL | |||
else | |||
LDLIBS += -lreadline | |||
endif | |||
ifeq ($(O_NOLOC),1) | |||
CPPFLAGS += -DNOLOCALE | |||
endif | |||
ifeq ($(shell $(PKG_CONFIG) ncursesw && echo 1),1) | |||
CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncursesw) | |||
LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs ncursesw) | |||
else ifeq ($(shell $(PKG_CONFIG) ncurses && echo 1),1) | |||
CFLAGS_CURSES ?= $(shell $(PKG_CONFIG) --cflags ncurses) | |||
LDLIBS_CURSES ?= $(shell $(PKG_CONFIG) --libs ncurses) | |||
else | |||
LDLIBS_CURSES ?= -lncurses | |||
endif | |||
ifeq ($(shell uname -s), Haiku) | |||
LDLIBS_HAIKU ?= -lstdc++ -lbe | |||
SRC_HAIKU ?= misc/haiku/nm.cpp | |||
OBJS_HAIKU ?= misc/haiku/nm.o | |||
endif | |||
CFLAGS += -Wall -Wextra | |||
CFLAGS += $(CFLAGS_OPTIMIZATION) | |||
CFLAGS += $(CFLAGS_CURSES) | |||
LDLIBS += $(LDLIBS_CURSES) $(LDLIBS_HAIKU) | |||
DISTFILES = src nnn.1 Makefile README.md LICENSE VERSION.mk | |||
SRC = src/nnn.c | |||
HEADERS = src/nnn.h | |||
BIN = nnn | |||
OBJS := nnn.o $(OBJS_HAIKU) | |||
all: $(BIN) | |||
ifeq ($(shell uname -s), Haiku) | |||
$(OBJS_HAIKU): $(SRC_HAIKU) | |||
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< | |||
endif | |||
nnn.o: $(SRC) $(HEADERS) | |||
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< | |||
$(BIN): $(OBJS) | |||
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) | |||
# targets for backwards compatibility | |||
debug: $(BIN) | |||
norl: $(BIN) | |||
noloc: $(BIN) | |||
install: all | |||
$(INSTALL) -m 0755 -d $(DESTDIR)$(PREFIX)/bin | |||
$(INSTALL) -m 0755 $(BIN) $(DESTDIR)$(PREFIX)/bin | |||
$(INSTALL) -m 0755 -d $(DESTDIR)$(MANPREFIX)/man1 | |||
$(INSTALL) -m 0644 $(BIN).1 $(DESTDIR)$(MANPREFIX)/man1 | |||
uninstall: | |||
$(RM) $(DESTDIR)$(PREFIX)/bin/$(BIN) | |||
$(RM) $(DESTDIR)$(MANPREFIX)/man1/$(BIN).1 | |||
strip: $(BIN) | |||
$(STRIP) $^ | |||
dist: | |||
mkdir -p nnn-$(VERSION) | |||
$(CP) -r $(DISTFILES) nnn-$(VERSION) | |||
mkdir -p nnn-$(VERSION)/misc | |||
$(CP) -r misc/haiku nnn-$(VERSION)/misc | |||
tar -cf nnn-$(VERSION).tar nnn-$(VERSION) | |||
gzip nnn-$(VERSION).tar | |||
$(RM) -r nnn-$(VERSION) | |||
clean: | |||
$(RM) -f $(BIN) $(OBJS) nnn-$(VERSION).tar.gz | |||
skip: ; | |||
.PHONY: all debug install uninstall strip dist clean |
@@ -0,0 +1,14 @@ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
typedef struct haiku_nm_t *haiku_nm_h; | |||
haiku_nm_h haiku_init_nm(); | |||
void haiku_close_nm(haiku_nm_h hnd); | |||
int haiku_watch_dir(haiku_nm_h hnd, const char *path); | |||
int haiku_stop_watch(haiku_nm_h hnd); | |||
int haiku_is_update_needed(haiku_nm_h hnd); | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -0,0 +1,83 @@ | |||
#include <Directory.h> | |||
#include <Looper.h> | |||
#include <NodeMonitor.h> | |||
#include <MessageFilter.h> | |||
#include "haiku_interop.h" | |||
filter_result dir_mon_flt(BMessage *message, BHandler **hnd, BMessageFilter *fltr) { | |||
(void) hnd; | |||
(void) fltr; | |||
if (message->what == B_NODE_MONITOR) { | |||
int32 val; | |||
message->FindInt32("opcode", &val); | |||
switch (val) { | |||
case B_ENTRY_CREATED: | |||
case B_ENTRY_MOVED: | |||
case B_ENTRY_REMOVED: | |||
return B_DISPATCH_MESSAGE; | |||
} | |||
} | |||
return B_SKIP_MESSAGE; | |||
} | |||
class DirectoryListener : public BLooper { | |||
public: | |||
bool recv_reset() { | |||
Lock(); | |||
bool val = _ev_on; | |||
_ev_on = false; | |||
Unlock(); | |||
return val; | |||
} | |||
private: | |||
void MessageReceived(BMessage * message) override { | |||
Lock(); | |||
_ev_on = true; | |||
Unlock(); | |||
BLooper::MessageReceived(message); | |||
} | |||
bool _ev_on = false; | |||
}; | |||
struct haiku_nm_t { | |||
haiku_nm_t() { | |||
dl = new DirectoryListener(); | |||
flt = new BMessageFilter(B_PROGRAMMED_DELIVERY, B_LOCAL_SOURCE, dir_mon_flt); | |||
dl->AddCommonFilter(flt); | |||
dl->Run(); | |||
} | |||
DirectoryListener *dl; | |||
BMessageFilter *flt; | |||
node_ref nr; | |||
}; | |||
haiku_nm_h haiku_init_nm() { | |||
return new haiku_nm_t(); | |||
} | |||
void haiku_close_nm(haiku_nm_h hnd) { | |||
delete hnd->flt; | |||
// This is the way of deleting a BLooper | |||
hnd->dl->PostMessage(B_QUIT_REQUESTED); | |||
delete hnd; | |||
} | |||
int haiku_watch_dir(haiku_nm_h hnd, const char *path) { | |||
BDirectory dir(path); | |||
dir.GetNodeRef(&(hnd->nr)); | |||
return watch_node(&(hnd->nr), B_WATCH_DIRECTORY, nullptr, hnd->dl); | |||
} | |||
int haiku_stop_watch(haiku_nm_h hnd) { | |||
return watch_node(&(hnd->nr), B_STOP_WATCHING, nullptr, hnd->dl); | |||
} | |||
int haiku_is_update_needed(haiku_nm_h hnd) { | |||
return hnd->dl->recv_reset(); | |||
} |
@@ -0,0 +1,52 @@ | |||
SUMMARY="The missing terminal file manager for X" | |||
DESCRIPTION=" | |||
nnn is a full-featured terminal file manager. It's tiny and nearly 0-config with an incredible performance. | |||
nnn is also a du analyzer, an app launcher, a batch renamer and a file picker. The plugin repository has tons of plugins and documentation to extend the capabilities further. You can plug new functionality and play with a custom keybind instantly. There's an independent (neo)vim plugin. | |||
It runs smoothly on the Raspberry Pi, Termux on Android, Linux, macOS, BSD, Cygwin, WSL and works seamlessly with DEs and GUI utilities. | |||
Visit the Wiki for concepts, program usage, how-tos and troubleshooting. | |||
" | |||
HOMEPAGE="https://github.com/jarun/nnn" | |||
COPYRIGHT="2016-2019 Arun Prakash Jana" | |||
LICENSE="BSD (2-clause)" | |||
REVISION="1" | |||
SOURCE_URI="git://github.com/jarun/nnn.git" | |||
ARCHITECTURES="x86 x86_64" | |||
PROVIDES=" | |||
nnn = $portVersion | |||
cmd:nnn = $portVersion | |||
" | |||
REQUIRES=" | |||
haiku | |||
lib:libncurses | |||
lib:libreadline | |||
" | |||
BUILD_REQUIRES=" | |||
haiku_devel | |||
pkgconfig | |||
devel:libncurses | |||
devel:libreadline | |||
" | |||
BUILD_PREREQUIRES=" | |||
cmd:make | |||
cmd:gcc | |||
cmd:g++ | |||
cmd:ld | |||
cmd:install | |||
" | |||
BUILD() | |||
{ | |||
make -f misc/haiku/Makefile | |||
} | |||
INSTALL() | |||
{ | |||
make -f misc/haiku/Makefile PREFIX=$prefix MANPREFIX=$manDir install | |||
} |
@@ -49,6 +49,9 @@ | |||
#include <sys/event.h> | |||
#include <sys/time.h> | |||
#define BSD_KQUEUE | |||
#elif defined(__HAIKU__) | |||
#include "../misc/haiku/haiku_interop.h" | |||
#define HAIKU_NM | |||
#else | |||
#include <sys/sysmacros.h> | |||
#endif | |||
@@ -570,6 +573,9 @@ static struct kevent events_to_monitor[NUM_EVENT_FDS]; | |||
static uint KQUEUE_FFLAGS = NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | |||
| NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE; | |||
static struct timespec gtimeout; | |||
#elif defined(HAIKU_NM) | |||
static bool haiku_nm_active = FALSE; | |||
static haiku_nm_h haiku_hnd = NULL; | |||
#endif | |||
/* Function macros */ | |||
@@ -1892,6 +1898,8 @@ static int nextsel(int presel) | |||
struct kevent event_data[NUM_EVENT_SLOTS]; | |||
memset((void *)event_data, 0x0, sizeof(struct kevent) * NUM_EVENT_SLOTS); | |||
#elif defined(HAIKU_NM) | |||
// TODO: Do some Haiku declarations | |||
#endif | |||
if (c == 0 || c == MSGWAIT) { | |||
@@ -1947,6 +1955,9 @@ static int nextsel(int presel) | |||
&& kevent(kq, events_to_monitor, NUM_EVENT_SLOTS, | |||
event_data, NUM_EVENT_FDS, >imeout) > 0) | |||
c = CONTROL('L'); | |||
#elif defined(HAIKU_NM) | |||
if (!cfg.selmode && !cfg.blkorder && haiku_nm_active && idle & 1 && haiku_is_update_needed(haiku_hnd)) | |||
c = CONTROL('L'); | |||
#endif | |||
} else | |||
idle = 0; | |||
@@ -3250,12 +3261,25 @@ static bool xmktree(char* path, bool dir) | |||
/* Create folder from path to '\0' inserted at p */ | |||
if (mkdir(path, 0777) == -1 && errno != EEXIST) { | |||
#ifdef __HAIKU__ | |||
// XDG_CONFIG_HOME contains a directory | |||
// that is read-only, but the full path | |||
// is writeable. | |||
// Try to continue and see what happens. | |||
// TODO: Find a more robust solution. | |||
if (errno == B_READ_ONLY_DEVICE) { | |||
goto next; | |||
} | |||
#endif | |||
DPRINTF_S("mkdir1!"); | |||
DPRINTF_S(strerror(errno)); | |||
*slash = '/'; | |||
return FALSE; | |||
} | |||
#ifdef __HAIKU__ | |||
next: | |||
#endif | |||
/* Restore path */ | |||
*slash = '/'; | |||
++p; | |||
@@ -3774,7 +3798,7 @@ static int dentfill(char *path, struct entry **dents) | |||
if (!dp) | |||
goto exit; | |||
#ifdef __sun | |||
#if defined(__sun) || defined(__HAIKU__) | |||
flags = AT_SYMLINK_NOFOLLOW; /* no d_type */ | |||
#else | |||
if (cfg.blkorder || dp->d_type == DT_UNKNOWN) { | |||
@@ -3878,7 +3902,7 @@ static int dentfill(char *path, struct entry **dents) | |||
/* Copy other fields */ | |||
dentp->t = cfg.mtime ? sb.st_mtime : sb.st_atime; | |||
#ifndef __sun | |||
#if !(defined(__sun) || defined(__HAIKU__)) | |||
if (!flags && dp->d_type == DT_LNK) { | |||
/* Do not add sizes for links */ | |||
dentp->mode = (sb.st_mode & ~S_IFMT) | S_IFLNK; | |||
@@ -3926,7 +3950,7 @@ static int dentfill(char *path, struct entry **dents) | |||
if (S_ISDIR(sb.st_mode)) | |||
dentp->flags |= DIR_OR_LINK_TO_DIR; | |||
#ifndef __sun /* no d_type */ | |||
#if !(defined(__sun) || defined(__HAIKU__)) /* no d_type */ | |||
} else if (dp->d_type == DT_DIR || (dp->d_type == DT_LNK && S_ISDIR(sb.st_mode))) { | |||
dentp->flags |= DIR_OR_LINK_TO_DIR; | |||
#endif | |||
@@ -4321,6 +4345,12 @@ begin: | |||
event_fd = -1; | |||
dir_changed = FALSE; | |||
} | |||
#elif defined(HAIKU_NM) | |||
if ((presel == FILTER || dir_changed) && haiku_hnd != NULL) { | |||
haiku_stop_watch(haiku_hnd); | |||
haiku_nm_active = FALSE; | |||
dir_changed = FALSE; | |||
} | |||
#endif | |||
/* Can fail when permissions change while browsing. | |||
@@ -4352,6 +4382,8 @@ begin: | |||
EV_SET(&events_to_monitor[0], event_fd, EVFILT_VNODE, | |||
EV_ADD | EV_CLEAR, KQUEUE_FFLAGS, 0, path); | |||
} | |||
#elif defined(HAIKU_NM) | |||
haiku_nm_active = haiku_watch_dir(haiku_hnd, path) == _SUCCESS; | |||
#endif | |||
while (1) { | |||
@@ -4726,6 +4758,11 @@ nochange: | |||
close(event_fd); | |||
event_fd = -1; | |||
} | |||
#elif defined(HAIKU_NM) | |||
if (haiku_nm_active) { | |||
haiku_stop_watch(haiku_hnd); | |||
haiku_nm_active = FALSE; | |||
} | |||
#endif | |||
presel = filterentries(path, lastname); | |||
@@ -5852,6 +5889,12 @@ int main(int argc, char *argv[]) | |||
xerror(); | |||
return _FAILURE; | |||
} | |||
#elif defined(HAIKU_NM) | |||
haiku_hnd = haiku_init_nm(); | |||
if (!haiku_hnd) { | |||
xerror(); | |||
return _FAILURE; | |||
} | |||
#endif | |||
/* Set nnn nesting level */ | |||
@@ -5950,6 +5993,8 @@ int main(int argc, char *argv[]) | |||
if (event_fd >= 0) | |||
close(event_fd); | |||
close(kq); | |||
#elif defined(HAIKU_NM) | |||
haiku_close_nm(haiku_hnd); | |||
#endif | |||
return _SUCCESS; | |||