* 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 | PREFIX ?= /usr/local | ||||
MANPREFIX ?= $(PREFIX)/share/man | MANPREFIX ?= $(PREFIX)/share/man | ||||
@@ -57,7 +57,7 @@ CFLAGS += $(CFLAGS_CURSES) | |||||
LDLIBS += $(LDLIBS_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 | SRC = src/nnn.c | ||||
HEADERS = src/nnn.h | HEADERS = src/nnn.h | ||||
BIN = nnn | 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/event.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#define BSD_KQUEUE | #define BSD_KQUEUE | ||||
#elif defined(__HAIKU__) | |||||
#include "../misc/haiku/haiku_interop.h" | |||||
#define HAIKU_NM | |||||
#else | #else | ||||
#include <sys/sysmacros.h> | #include <sys/sysmacros.h> | ||||
#endif | #endif | ||||
@@ -570,6 +573,9 @@ static struct kevent events_to_monitor[NUM_EVENT_FDS]; | |||||
static uint KQUEUE_FFLAGS = NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | static uint KQUEUE_FFLAGS = NOTE_DELETE | NOTE_EXTEND | NOTE_LINK | ||||
| NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE; | | NOTE_RENAME | NOTE_REVOKE | NOTE_WRITE; | ||||
static struct timespec gtimeout; | static struct timespec gtimeout; | ||||
#elif defined(HAIKU_NM) | |||||
static bool haiku_nm_active = FALSE; | |||||
static haiku_nm_h haiku_hnd = NULL; | |||||
#endif | #endif | ||||
/* Function macros */ | /* Function macros */ | ||||
@@ -1892,6 +1898,8 @@ static int nextsel(int presel) | |||||
struct kevent event_data[NUM_EVENT_SLOTS]; | struct kevent event_data[NUM_EVENT_SLOTS]; | ||||
memset((void *)event_data, 0x0, sizeof(struct kevent) * NUM_EVENT_SLOTS); | memset((void *)event_data, 0x0, sizeof(struct kevent) * NUM_EVENT_SLOTS); | ||||
#elif defined(HAIKU_NM) | |||||
// TODO: Do some Haiku declarations | |||||
#endif | #endif | ||||
if (c == 0 || c == MSGWAIT) { | if (c == 0 || c == MSGWAIT) { | ||||
@@ -1947,6 +1955,9 @@ static int nextsel(int presel) | |||||
&& kevent(kq, events_to_monitor, NUM_EVENT_SLOTS, | && kevent(kq, events_to_monitor, NUM_EVENT_SLOTS, | ||||
event_data, NUM_EVENT_FDS, >imeout) > 0) | event_data, NUM_EVENT_FDS, >imeout) > 0) | ||||
c = CONTROL('L'); | 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 | #endif | ||||
} else | } else | ||||
idle = 0; | idle = 0; | ||||
@@ -3250,12 +3261,25 @@ static bool xmktree(char* path, bool dir) | |||||
/* Create folder from path to '\0' inserted at p */ | /* Create folder from path to '\0' inserted at p */ | ||||
if (mkdir(path, 0777) == -1 && errno != EEXIST) { | 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("mkdir1!"); | ||||
DPRINTF_S(strerror(errno)); | DPRINTF_S(strerror(errno)); | ||||
*slash = '/'; | *slash = '/'; | ||||
return FALSE; | return FALSE; | ||||
} | } | ||||
#ifdef __HAIKU__ | |||||
next: | |||||
#endif | |||||
/* Restore path */ | /* Restore path */ | ||||
*slash = '/'; | *slash = '/'; | ||||
++p; | ++p; | ||||
@@ -3774,7 +3798,7 @@ static int dentfill(char *path, struct entry **dents) | |||||
if (!dp) | if (!dp) | ||||
goto exit; | goto exit; | ||||
#ifdef __sun | #if defined(__sun) || defined(__HAIKU__) | ||||
flags = AT_SYMLINK_NOFOLLOW; /* no d_type */ | flags = AT_SYMLINK_NOFOLLOW; /* no d_type */ | ||||
#else | #else | ||||
if (cfg.blkorder || dp->d_type == DT_UNKNOWN) { | if (cfg.blkorder || dp->d_type == DT_UNKNOWN) { | ||||
@@ -3878,7 +3902,7 @@ static int dentfill(char *path, struct entry **dents) | |||||
/* Copy other fields */ | /* Copy other fields */ | ||||
dentp->t = cfg.mtime ? sb.st_mtime : sb.st_atime; | dentp->t = cfg.mtime ? sb.st_mtime : sb.st_atime; | ||||
#ifndef __sun | #if !(defined(__sun) || defined(__HAIKU__)) | ||||
if (!flags && dp->d_type == DT_LNK) { | if (!flags && dp->d_type == DT_LNK) { | ||||
/* Do not add sizes for links */ | /* Do not add sizes for links */ | ||||
dentp->mode = (sb.st_mode & ~S_IFMT) | S_IFLNK; | 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)) | if (S_ISDIR(sb.st_mode)) | ||||
dentp->flags |= DIR_OR_LINK_TO_DIR; | 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))) { | } else if (dp->d_type == DT_DIR || (dp->d_type == DT_LNK && S_ISDIR(sb.st_mode))) { | ||||
dentp->flags |= DIR_OR_LINK_TO_DIR; | dentp->flags |= DIR_OR_LINK_TO_DIR; | ||||
#endif | #endif | ||||
@@ -4321,6 +4345,12 @@ begin: | |||||
event_fd = -1; | event_fd = -1; | ||||
dir_changed = FALSE; | 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 | #endif | ||||
/* Can fail when permissions change while browsing. | /* Can fail when permissions change while browsing. | ||||
@@ -4352,6 +4382,8 @@ begin: | |||||
EV_SET(&events_to_monitor[0], event_fd, EVFILT_VNODE, | EV_SET(&events_to_monitor[0], event_fd, EVFILT_VNODE, | ||||
EV_ADD | EV_CLEAR, KQUEUE_FFLAGS, 0, path); | EV_ADD | EV_CLEAR, KQUEUE_FFLAGS, 0, path); | ||||
} | } | ||||
#elif defined(HAIKU_NM) | |||||
haiku_nm_active = haiku_watch_dir(haiku_hnd, path) == _SUCCESS; | |||||
#endif | #endif | ||||
while (1) { | while (1) { | ||||
@@ -4726,6 +4758,11 @@ nochange: | |||||
close(event_fd); | close(event_fd); | ||||
event_fd = -1; | event_fd = -1; | ||||
} | } | ||||
#elif defined(HAIKU_NM) | |||||
if (haiku_nm_active) { | |||||
haiku_stop_watch(haiku_hnd); | |||||
haiku_nm_active = FALSE; | |||||
} | |||||
#endif | #endif | ||||
presel = filterentries(path, lastname); | presel = filterentries(path, lastname); | ||||
@@ -5852,6 +5889,12 @@ int main(int argc, char *argv[]) | |||||
xerror(); | xerror(); | ||||
return _FAILURE; | return _FAILURE; | ||||
} | } | ||||
#elif defined(HAIKU_NM) | |||||
haiku_hnd = haiku_init_nm(); | |||||
if (!haiku_hnd) { | |||||
xerror(); | |||||
return _FAILURE; | |||||
} | |||||
#endif | #endif | ||||
/* Set nnn nesting level */ | /* Set nnn nesting level */ | ||||
@@ -5950,6 +5993,8 @@ int main(int argc, char *argv[]) | |||||
if (event_fd >= 0) | if (event_fd >= 0) | ||||
close(event_fd); | close(event_fd); | ||||
close(kq); | close(kq); | ||||
#elif defined(HAIKU_NM) | |||||
haiku_close_nm(haiku_hnd); | |||||
#endif | #endif | ||||
return _SUCCESS; | return _SUCCESS; | ||||