wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit df407fd8cde2c2a9c19969fb40328f94ff1b048e
parent f137735249b8fe732de47ae5ccbc92de12953a84
Author: Anselm R. Garbe <garbeam@wmii.de>
Date:   Mon, 30 Jan 2006 20:08:58 +0200

removed old libixp crap, now several things are broken and will settle after a while


Diffstat:
Makefile | 2+-
cmd/Makefile | 22+++++-----------------
cmd/wm/client.c | 4++--
cmd/wm/wm.c | 12++++++------
cmd/wm/wm.h | 74+++++++++++++++++---------------------------------------------------------
cmd/wmiibar.c | 2+-
cmd/wmiir.c | 377++++++++++++++++++++++++++++++++++++++++---------------------------------------
cmd/wmiir2.c | 236-------------------------------------------------------------------------------
libixp/Makefile | 5++---
libixp/client.c | 400++++++++++++++++++++++++++++++-------------------------------------------------
libixp/convert.c | 197+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libixp/ixp.h | 413+++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
libixp/message.c | 431+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
libixp/ramfs.c | 297-------------------------------------------------------------------------------
libixp/server.c | 453++++++++-----------------------------------------------------------------------
libixp/socket.c | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libixp/transport.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
libixp2/Makefile | 25-------------------------
libixp2/client.c | 194-------------------------------------------------------------------------------
libixp2/convert.c | 197-------------------------------------------------------------------------------
libixp2/ixp.h | 289------------------------------------------------------------------------------
libixp2/message.c | 317-------------------------------------------------------------------------------
libixp2/server.c | 73-------------------------------------------------------------------------
libixp2/socket.c | 204-------------------------------------------------------------------------------
libixp2/transport.c | 81-------------------------------------------------------------------------------
libwmii/Makefile | 2+-
libwmii/ixputil.c | 98-------------------------------------------------------------------------------
libwmii/wmii.h | 6------
28 files changed, 1457 insertions(+), 3239 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,7 +3,7 @@ include config.mk -SUBDIRS = libcext liblitz libixp libixp2 libwmii cmd +SUBDIRS = libcext liblitz libixp libwmii cmd BIN = cmd/wm/wmii cmd/wm/wmiiwm cmd/wmiibar cmd/wmiifs \ cmd/wmiikeys cmd/wmiimenu cmd/wmiiplumb cmd/wmiir cmd/wmiir2 cmd/wmiiwarp diff --git a/cmd/Makefile b/cmd/Makefile @@ -5,9 +5,7 @@ include ../config.mk CFLAGS += -I../liblitz -I../libixp -I../libwmii -I../libcext LDFLAGS += -L../liblitz -llitz -L../libixp -lixp \ - -L../libwmii -lwmii -L../libcext -lcext -LDFLAGS2 += ${LIBS} -L../liblitz -llitz -L../libixp2 -lixp \ - -L../libwmii -lwmii -L../libcext -lcext + -L../libwmii -lwmii -L../libcext -lcext SRC_bar = wmiibar.c OBJ_bar = ${SRC_bar:.c=.o} @@ -15,9 +13,6 @@ OBJ_bar = ${SRC_bar:.c=.o} SRC_menu = wmiimenu.c OBJ_menu = ${SRC_menu:.c=.o} -SRC_r2 = wmiir2.c -OBJ_r2 = ${SRC_r2:.c=.o} - SRC_r = wmiir.c OBJ_r = ${SRC_r:.c=.o} @@ -33,7 +28,8 @@ OBJ_plumb = ${SRC_plumb:.c=.o} SRC_warp = wmiiwarp.c OBJ_warp = ${SRC_warp:.c=.o} -all: wmiibar wmiimenu wmiir wmiir2 wmiifs wmiikeys wmiiplumb wmiiwarp +#all: wmiibar wmiimenu wmiir wmiifs wmiikeys wmiiplumb wmiiwarp +all: wmiibar wmiir wmiiplumb wmiiwarp @echo built wmii commands .c.o: @@ -42,9 +38,9 @@ all: wmiibar wmiimenu wmiir wmiir2 wmiifs wmiikeys wmiiplumb wmiiwarp wmiibar: ${OBJ_bar} @echo LD $@ - @${CC} -o $@ ${OBJ_bar} ${LDFLAGS2} + @${CC} -o $@ ${OBJ_bar} ${LDFLAGS} # Solaris -# @${CC} -o $@ ${OBJ_bar2} ${LDFLAGS2} -lsocket +# @${CC} -o $@ ${OBJ_bar} ${LDFLAGS} -lsocket wmiimenu: ${OBJ_menu} @echo LD $@ @@ -52,14 +48,6 @@ wmiimenu: ${OBJ_menu} # Solaris # @${CC} -o $@ ${OBJ_menu} ${LDFLAGS} -lsocket -wmiir2: ${OBJ_r2} - @echo LD $@ - @${CC} -o $@ ${OBJ_r2} -g -static -L${PREFIX}/lib -L/usr/lib -lc \ - -L../libixp2 -lixp -L../libcext -lcext -# Solaris -# @${CC} -o $@ ${OBJ_r2} -g -static -L${PREFIX}/lib -L/usr/lib -lc \ -# -L../libixp2 -lixp -L../libcext -lcext -lsocket - wmiir: ${OBJ_r} @echo LD $@ @${CC} -o $@ ${OBJ_r} -g -static -L${PREFIX}/lib -L/usr/lib -lc \ diff --git a/cmd/wm/client.c b/cmd/wm/client.c @@ -291,7 +291,7 @@ draw_client(Client *c) XRectangle notch; d.drawable = c->frame.win; - d.font = font; + d.xfont = xfont; d.gc = c->frame.gc; if(c == sel_client()) { @@ -476,7 +476,7 @@ unsigned int tab_height(Client * c) { if(blitz_strtonum(c->file[C_TAB]->content, 0, 1)) - return font->ascent + font->descent + 4; + return xfont->ascent + xfont->descent + 4; return 0; } diff --git a/cmd/wm/wm.c b/cmd/wm/wm.c @@ -8,7 +8,7 @@ #include <string.h> #include <sys/stat.h> #include <sys/wait.h> -#include <X11/cursorfont.h> +#include <X11/cursorxfont.h> #include <X11/Xproto.h> #include <X11/keysym.h> #include <X11/Xatom.h> @@ -177,7 +177,7 @@ draw_pager() th = ((double) tw / rect.width) * rect.height; d.drawable = transient; d.gc = gc_transient; - d.font = font; + d.xfont = xfont; i = 0; for(ir = 0; ir < rows; ir++) { for(ic = 0; ic < cols; ic++) { @@ -563,8 +563,8 @@ handle_after_write(IXPServer * s, File * f) &color_xor, &color_xor); XSetForeground(dpy, gc_xor, color_xor.pixel); } else if(f == def[WM_FONT]) { - XFreeFont(dpy, font); - font = blitz_getfont(dpy, def[WM_FONT]->content); + XFreeFont(dpy, xfont); + xfont = blitz_getxfont(dpy, def[WM_FONT]->content); } check_event(0); } @@ -625,7 +625,7 @@ init_default() BLITZ_NORM_FG_COLOR); def[WM_NORM_BORDER_COLOR] = wmii_create_ixpfile(ixps, "/default/nstyle/bordercolor", BLITZ_NORM_BORDER_COLOR); - def[WM_FONT] = wmii_create_ixpfile(ixps, "/default/font", BLITZ_FONT); + def[WM_FONT] = wmii_create_ixpfile(ixps, "/default/xfont", BLITZ_FONT); def[WM_FONT]->after_write = handle_after_write; def[WM_SNAP_VALUE] = wmii_create_ixpfile(ixps, "/default/snapvalue", "20"); /* 0..1000 */ def[WM_BORDER] = wmii_create_ixpfile(ixps, "/default/border", "1"); @@ -803,7 +803,7 @@ main(int argc, char *argv[]) init_atoms(); init_cursors(); init_default(); - font = blitz_getfont(dpy, def[WM_FONT]->content); + xfont = blitz_getxfont(dpy, def[WM_FONT]->content); wmii_init_lock_modifiers(dpy, &valid_mask, &num_lock_mask); init_screen(); scan_wins(); diff --git a/cmd/wm/wm.h b/cmd/wm/wm.h @@ -9,56 +9,6 @@ #include "wmii.h" -/* array indexes of page file pointers */ -enum { - P_PREFIX, - P_NAME, - P_CLIENT_PREFIX, - P_SEL_PREFIX, - P_CTL, - P_LAST -}; - -/* array indexes of frame file pointers */ -enum { - C_PREFIX, - C_NAME, - C_GEOMETRY, - C_BORDER, - C_TAB, - C_HANDLE_INC, - C_CTL, - C_LAST -}; - -/* array indexes of wm file pointers */ -enum { - WM_CTL, - WM_TRANS_COLOR, - WM_COLUMN_GEOMETRY, - WM_SEL_BG_COLOR, - WM_SEL_BORDER_COLOR, - WM_SEL_FG_COLOR, - WM_NORM_BG_COLOR, - WM_NORM_BORDER_COLOR, - WM_NORM_FG_COLOR, - WM_FONT, - WM_BORDER, - WM_TAB, - WM_HANDLE_INC, - WM_SNAP_VALUE, - WM_DETACHED_PREFIX, - WM_SEL_PAGE, - WM_EVENT_PAGE_UPDATE, - WM_EVENT_CLIENT_UPDATE, - WM_EVENT_B1PRESS, - WM_EVENT_B2PRESS, - WM_EVENT_B3PRESS, - WM_EVENT_B4PRESS, - WM_EVENT_B5PRESS, - WM_LAST -}; - /* array indexes of EWMH window properties */ /* TODO: set / react */ enum { @@ -96,7 +46,6 @@ struct Page { size_t sel_column; Bool is_column; XRectangle rect_column; - File *file[P_LAST]; }; struct Client { @@ -104,6 +53,7 @@ struct Client { int proto; unsigned int border; unsigned int ignore_unmap; + Bool handle_inc; Bool destroyed; Bool maximized; Bool attached; @@ -119,8 +69,8 @@ struct Client { XRectangle revert; GC gc; Cursor cursor; + Bool title; } frame; - File *file[C_LAST]; }; /* global variables */ @@ -140,11 +90,22 @@ int screen; Window root; Window transient; /* pager / attach */ XRectangle rect; -XFontStruct *font; +XFontStruct *xfont; XColor color_xor; GC gc_xor; GC gc_transient; +/* default values */ +typedef struct { + char xorcolor[24]; + char selcolor[24]; + char normcolor[24]; + char font[24]; + unsigned int border; + unsigned int title; + unsigned int snap; +} Default def; + Atom wm_state; /* TODO: Maybe replace with wm_atoms[WM_ATOM_COUNT]? */ Atom wm_change_state; Atom wm_protocols; @@ -165,9 +126,6 @@ Cursor ne_cursor; Cursor sw_cursor; Cursor se_cursor; -/* default file pointers */ -File *def[WM_LAST]; - unsigned int valid_mask, num_lock_mask; @@ -222,12 +180,14 @@ void select_column(Client *c, char *arg); void new_column(Page *p); /* wm.c */ +/* void invoke_wm_event(File * f); void run_action(File * f, void *obj, Action * acttbl); +*/ void scan_wins(); Client *win_to_client(Window w); int win_proto(Window w); int win_state(Window w); -void handle_after_write(IXPServer * s, File * f); +/*void handle_after_write(IXPServer * s, File * f);*/ void detach(Client * f, int client_destroyed); void set_client_state(Client * c, int state); diff --git a/cmd/wmiibar.c b/cmd/wmiibar.c @@ -18,7 +18,7 @@ #include <X11/Xutil.h> #include <sys/socket.h> -#include "../libixp2/ixp.h" +#include "ixp.h" #include "blitz.h" /* diff --git a/cmd/wmiir.c b/cmd/wmiir.c @@ -6,11 +6,14 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> +#include <dirent.h> #include "ixp.h" -static IXPClient *c; -static int exit_code = 0; +#include <cext.h> + +static IXPClient c = { 0 }; static char *version[] = { "wmiir - window manager improved remote - " VERSION "\n" @@ -21,211 +24,213 @@ static void usage() { fprintf(stderr, "%s", - "usage: wmiir [-s <socket file>] [-v] <action> <action_arg> [...]\n" - " -s socket file (default: $WMIIR_SOCKET)\n" - " -f read actions from stdin\n" + "usage: wmiir [-a <server address>] [-v] <command>\n" + " -a server address (default: $WMIIR_ADDRESS)\n" " -v version info\n" - "actions:\n" - " create <file> [<content>] -- creates and optionally writes content to a file\n" - " write <file> <content> -- writes content to a file\n" - " read <directory/file> -- reads file or directory contents\n" - " remove <directory/file> -- removes file or directory, use with care!\n"); + "valid commands:\n" + " create <file> -- creates file and writes data from stdin to file\n" + " read <file/dir> -- prints file/directory contents\n" + " write <file> -- writes data from stdin to file\n" + " remove <file> -- removes file\n"); exit(1); } static void -perform(char *action, char *file, char *content) +write_data(unsigned int fid) { - size_t out_len = 0; - char output[2050]; - int crt, fd = -1; - - if(!action) - return; - - crt = !strncmp(action, "create", 7); - if(!strncmp(action, "write", 6) || crt) { - if(!file) - return; - /* create file first */ - if(crt) { - c->create(c, file); - if(c->errstr) { - fprintf(stderr, "wmiir: error: create %s: %s\n", file, - c->errstr); - exit_code = 1; - return; - } - } - if(!content) - return; - fd = c->open(c, file); - if(c->errstr) { - fprintf(stderr, "wmiir: error: open %s: %s\n", file, - c->errstr); - exit_code = 1; - return; - } - c->write(c, fd, content, strlen(content)); - if(c->errstr) { - fprintf(stderr, "wmiir: error: write %s: %s\n", file, - c->errstr); - exit_code = 1; - if(!strncmp(c->errstr, DEAD_SERVER, strlen(DEAD_SERVER) + 1)) - return; - } - } else if(!strncmp(action, "read", 5)) { - if(!file) - return; - fd = c->open(c, file); - if(c->errstr) { - fprintf(stderr, "wmiir: error: open %s: %s\n", file, - c->errstr); - exit_code = 1; - return; - } - do { - out_len = c->read(c, fd, output, 2048); - if(c->errstr) { - fprintf(stderr, "wmiir: error: read %s: %s\n", file, - c->errstr); - exit_code = 1; - if(!strncmp - (c->errstr, DEAD_SERVER, strlen(DEAD_SERVER) + 1)) - return; - break; - } - output[out_len] = 0; - fprintf(stdout, "%s", output); - } - while(out_len == 2048); - fprintf(stdout, "%s", "\n"); - } else if(!strncmp(action, "remove", 7)) { - if(!file) - return; - c->remove(c, file); - if(c->errstr) { - fprintf(stderr, "wmiir: error: remove %s: %s\n", file, - c->errstr); - exit_code = 1; - return; + void *data = cext_emallocz(c.fcall.iounit); + unsigned long long offset = 0; + size_t len = 0; + + while((len = read(0, data, c.fcall.iounit)) > 0) { + fprintf(stderr, "read=%d, bufsz=%d\n", len, c.fcall.iounit); + if(ixp_client_write + (&c, fid, offset, len, data) != len) { + fprintf(stderr, "wmiir: cannot write file: %s\n", c.errstr); + break; } + offset += len; } - if(fd != -1) { - c->close(c, fd); - if(c->errstr) { - fprintf(stderr, "wmiir: error: close %s: %s\n", file, - c->errstr); - exit_code = 1; - return; - } + free(data); +} + +static int +xcreate(char *file) +{ + unsigned int fid; + char *p = strrchr(file, '/'); + + fid = c.root_fid << 2; + /* walk to bottom-most directory */ + *p = 0; + if(ixp_client_walk(&c, fid, file) == -1) { + fprintf(stderr, "wmiir: cannot walk to '%s': %s\n", file, c.errstr); + return -1; + } + /* create */ + p++; + if(ixp_client_create(&c, fid, p, (unsigned int) 0xff, IXP_OWRITE) == -1) { + fprintf(stderr, "wmiir: cannot create file '%s': %s\n", p, c.errstr); + return -1; } + write_data(fid); + return ixp_client_close(&c, fid); +} + +static int +xwrite(char *file) +{ + + /* open */ + unsigned int fid = c.root_fid << 2; + if(ixp_client_open(&c, fid, file, IXP_OWRITE) == -1) { + fprintf(stderr, "wmiir: cannot open file '%s': %s\n", file, c.errstr); + return -1; + } + write_data(fid); + return ixp_client_close(&c, fid); +} + +static int +comp(const void *s1, const void *s2) +{ + return strcmp(*(char **)s1, *(char **)s2); +} + +static void +xls(void *result, unsigned int msize) +{ + size_t n = 0, j = 0; + char buf[IXP_MAX_FLEN]; + void *p = result; + char **dir; + static Stat stat, zerostat = { 0 }; + do { + p = ixp_dec_stat(p, &stat); + n++; + } + while(p - result < msize); + dir = (char **)cext_emallocz(sizeof(char *) * n); + p = result; + do { + p = ixp_dec_stat(p, &stat); + if(stat.qid.type == IXP_QTDIR) + snprintf(buf, sizeof(buf), "%s/", stat.name); + else + snprintf(buf, sizeof(buf), "%s", stat.name); + dir[j++] = cext_estrdup(buf); + stat = zerostat; + } + while(p - result < msize); + qsort(dir, n, sizeof(char *), comp); + for(j = 0; j < n; j++) { + fprintf(stdout, "%s\n", dir[j]); + free(dir[j]); + } + free(dir); +} + +static int +xread(char *file) +{ + unsigned int fid = c.root_fid << 2; + int count, is_directory = 0; + static unsigned char result[IXP_MAX_MSG]; + unsigned long long offset = 0; + + /* open */ + if(ixp_client_open(&c, fid, file, IXP_OREAD) == -1) { + fprintf(stderr, "wmiir: cannot open file '%s': %s\n", file, c.errstr); + return -1; + } + is_directory = !c.fcall.nwqid || (c.fcall.qid.type == IXP_QTDIR); + + /* read */ + while((count = ixp_client_read(&c, fid, offset, result, IXP_MAX_MSG)) > 0) { + if(is_directory) + xls(result, count); + else { + unsigned int i; + for(i = 0; i < count; i++) + fputc(result[i], stdout); + fflush(stdout); + } + offset += count; + } + if(count == -1) { + fprintf(stderr, "wmiir: cannot read file/directory '%s': %s\n", file, c.errstr); + return -1; + } + return ixp_client_close(&c, fid); +} + +static int +xremove(char *file) +{ + unsigned int fid; + + /* remove */ + fid = c.root_fid << 2; + if(ixp_client_remove(&c, fid, file) == -1) { + fprintf(stderr, "wmiir: cannot remove file '%s': %s\n", file, c.errstr); + return -1; + } + return 0; } int main(int argc, char *argv[]) { - int i = 0, read_stdin = 0; - char line[4096], *p; - char *sockfile = getenv("WMIIR_SOCKET"); + int i = 0; + char *cmd, *file, *sockfile = getenv("WMIIR_ADDRESS"); /* command line args */ - if(argc > 1) { - for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { - switch (argv[i][1]) { - case 'v': - fprintf(stderr, "%s", version[0]); - exit(0); - break; - case 's': - if(i + 1 < argc) { - sockfile = argv[++i]; - } else { - usage(); - } - break; - case 'f': - read_stdin = 1; - break; - default: - usage(); - break; - } - } - } - if((argc <= 1) || (!read_stdin && (i + 1) >= argc)) { - fprintf(stderr, "%s", "wmiir: arguments: "); - for(i = 1; i < argc; i++) - fprintf(stderr, "%s, ", argv[i]); - fprintf(stderr, "%s", "\n"); - usage(); - } + if(argc < 2) + usage(); + + for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { + switch (argv[i][1]) { + case 'v': + fprintf(stderr, "%s", version[0]); + exit(0); + break; + case 'a': + if(i + 1 < argc) + sockfile = argv[++i]; + else + usage(); + break; + default: + usage(); + break; + } + } + cmd = argv[argc - 2]; + file = argv[argc - 1]; + if(!sockfile) { - fprintf(stderr, "%s", - "wmiir: error: WMIIR_SOCKET environment not set\n"); + fprintf(stderr, "%s", "wmiir: error: $WMIIR_ADDRESS not set\n"); usage(); } /* open socket */ - if(!(c = init_ixp_client(sockfile))) { - fprintf(stderr, "wmiir: cannot connect to server '%s'\n", - sockfile); + if(ixp_client_init(&c, sockfile) == -1) { + fprintf(stderr, "wmiir: %s\n", c.errstr); exit(1); } - if(read_stdin) { - /* simple shell */ - char *action, *file, *content; - while(fgets(line, 4096, stdin)) { - p = line; - while(*p != 0 && (*p == ' ' || *p == '\t')) - p++; - if(*p == 0) - continue; /* empty line */ - if(strncmp(p, "create ", 7) && - strncmp(p, "write ", 6) && - strncmp(p, "read ", 5) && strncmp(p, "remove ", 7)) - continue; - - action = p; - while(*p != 0 && *p != ' ' && *p != '\t' && *p != '\n') - p++; - if(*p == 0 || *p == '\n') - continue; /* ignore bogus command */ - *p = 0; - p++; - while(*p != 0 && (*p == ' ' || *p == '\t')) - p++; - if(*p == 0) - continue; /* ignore bogus command */ - file = p; - while(*p != 0 && *p != ' ' && *p != '\t' && *p != '\n') - p++; - if(*p == 0 || *p == '\n') { - content = 0; - *p = 0; - } else { - *p = 0; - p++; - content = p; - } - if(file[0] == 0) - continue; - if(content) { - static size_t len; - if((len = strlen(content))) - content[len - 1] = 0; - } - perform(action, file, content); - if(c->errstr) - fprintf(stderr, "wmiir: error: read %s: %s\n", file, - c->errstr); - } - } else { - perform(argv[i], argv[i + 1], (i + 2) < argc ? argv[i + 2] : 0); - } - if(c->errstr) { - deinit_client(c); - exit_code = 1; - } - return exit_code; + if(!strncmp(cmd, "create", 7)) + xcreate(file); + else if(!strncmp(cmd, "write", 6)) + xwrite(file); + else if(!strncmp(cmd, "read", 5)) + xread(file); + else if(!strncmp(cmd, "remove", 7)) + xremove(file); + else + usage(); + + /* close socket */ + ixp_client_deinit(&c); + + return 0; } diff --git a/cmd/wmiir2.c b/cmd/wmiir2.c @@ -1,236 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <dirent.h> - -#include "../libixp2/ixp.h" - -#include <cext.h> - -static IXPClient c = { 0 }; - -static char *version[] = { - "wmiir - window manager improved remote - " VERSION "\n" - " (C)opyright MMIV-MMVI Anselm R. Garbe\n", 0 -}; - -static void -usage() -{ - fprintf(stderr, "%s", - "usage: wmiir [-a <server address>] [-v] <command>\n" - " -a server address (default: $WMIIR_ADDRESS)\n" - " -v version info\n" - "valid commands:\n" - " create <file> -- creates file and writes data from stdin to file\n" - " read <file/dir> -- prints file/directory contents\n" - " write <file> -- writes data from stdin to file\n" - " remove <file> -- removes file\n"); - exit(1); -} - -static void -write_data(unsigned int fid) -{ - void *data = cext_emallocz(c.fcall.iounit); - unsigned long long offset = 0; - size_t len = 0; - - while((len = read(0, data, c.fcall.iounit)) > 0) { - fprintf(stderr, "read=%d, bufsz=%d\n", len, c.fcall.iounit); - if(ixp_client_write - (&c, fid, offset, len, data) != len) { - fprintf(stderr, "wmiir: cannot write file: %s\n", c.errstr); - break; - } - offset += len; - } - free(data); -} - -static int -xcreate(char *file) -{ - unsigned int fid; - char *p = strrchr(file, '/'); - - fid = c.root_fid << 2; - /* walk to bottom-most directory */ - *p = 0; - if(ixp_client_walk(&c, fid, file) == -1) { - fprintf(stderr, "wmiir: cannot walk to '%s': %s\n", file, c.errstr); - return -1; - } - /* create */ - p++; - if(ixp_client_create(&c, fid, p, (unsigned int) 0xff, IXP_OWRITE) == -1) { - fprintf(stderr, "wmiir: cannot create file '%s': %s\n", p, c.errstr); - return -1; - } - write_data(fid); - return ixp_client_close(&c, fid); -} - -static int -xwrite(char *file) -{ - - /* open */ - unsigned int fid = c.root_fid << 2; - if(ixp_client_open(&c, fid, file, IXP_OWRITE) == -1) { - fprintf(stderr, "wmiir: cannot open file '%s': %s\n", file, c.errstr); - return -1; - } - write_data(fid); - return ixp_client_close(&c, fid); -} - -static int -comp(const void *s1, const void *s2) -{ - return strcmp(*(char **)s1, *(char **)s2); -} - -static void -xls(void *result, unsigned int msize) -{ - size_t n = 0, j = 0; - char buf[IXP_MAX_FLEN]; - void *p = result; - char **dir; - static Stat stat, zerostat = { 0 }; - do { - p = ixp_dec_stat(p, &stat); - n++; - } - while(p - result < msize); - dir = (char **)cext_emallocz(sizeof(char *) * n); - p = result; - do { - p = ixp_dec_stat(p, &stat); - if(stat.qid.type == IXP_QTDIR) - snprintf(buf, sizeof(buf), "%s/", stat.name); - else - snprintf(buf, sizeof(buf), "%s", stat.name); - dir[j++] = cext_estrdup(buf); - stat = zerostat; - } - while(p - result < msize); - qsort(dir, n, sizeof(char *), comp); - for(j = 0; j < n; j++) { - fprintf(stdout, "%s\n", dir[j]); - free(dir[j]); - } - free(dir); -} - -static int -xread(char *file) -{ - unsigned int fid = c.root_fid << 2; - int count, is_directory = 0; - static unsigned char result[IXP_MAX_MSG]; - unsigned long long offset = 0; - - /* open */ - if(ixp_client_open(&c, fid, file, IXP_OREAD) == -1) { - fprintf(stderr, "wmiir: cannot open file '%s': %s\n", file, c.errstr); - return -1; - } - is_directory = !c.fcall.nwqid || (c.fcall.qid.type == IXP_QTDIR); - - /* read */ - while((count = ixp_client_read(&c, fid, offset, result, IXP_MAX_MSG)) > 0) { - if(is_directory) - xls(result, count); - else { - unsigned int i; - for(i = 0; i < count; i++) - fputc(result[i], stdout); - fflush(stdout); - } - offset += count; - } - if(count == -1) { - fprintf(stderr, "wmiir: cannot read file/directory '%s': %s\n", file, c.errstr); - return -1; - } - return ixp_client_close(&c, fid); -} - -static int -xremove(char *file) -{ - unsigned int fid; - - /* remove */ - fid = c.root_fid << 2; - if(ixp_client_remove(&c, fid, file) == -1) { - fprintf(stderr, "wmiir: cannot remove file '%s': %s\n", file, c.errstr); - return -1; - } - return 0; -} - -int -main(int argc, char *argv[]) -{ - int i = 0; - char *cmd, *file, *sockfile = getenv("WMIIR_ADDRESS"); - - /* command line args */ - if(argc < 2) - usage(); - - for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { - switch (argv[i][1]) { - case 'v': - fprintf(stderr, "%s", version[0]); - exit(0); - break; - case 'a': - if(i + 1 < argc) - sockfile = argv[++i]; - else - usage(); - break; - default: - usage(); - break; - } - } - cmd = argv[argc - 2]; - file = argv[argc - 1]; - - if(!sockfile) { - fprintf(stderr, "%s", "wmiir: error: $WMIIR_ADDRESS not set\n"); - usage(); - } - /* open socket */ - if(ixp_client_init(&c, sockfile) == -1) { - fprintf(stderr, "wmiir: %s\n", c.errstr); - exit(1); - } - - if(!strncmp(cmd, "create", 7)) - xcreate(file); - else if(!strncmp(cmd, "write", 6)) - xwrite(file); - else if(!strncmp(cmd, "read", 5)) - xread(file); - else if(!strncmp(cmd, "remove", 7)) - xremove(file); - else - usage(); - - /* close socket */ - ixp_client_deinit(&c); - - return 0; -} diff --git a/libixp/Makefile b/libixp/Makefile @@ -4,14 +4,13 @@ include ../config.mk CFLAGS += -I ../libcext -LDFLAGS += -L../libcext -lcext -SRC = client.c message.c ramfs.c server.c +SRC = client.c convert.c message.c server.c socket.c transport.c OBJ = ${SRC:.c=.o} all: libixp - @echo built libixp + @echo built libixp2 .c.o: @echo CC $< diff --git a/libixp/client.c b/libixp/client.c @@ -3,288 +3,192 @@ * See LICENSE file for license details. */ -#include <errno.h> -#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <sys/stat.h> #include <sys/socket.h> -#include <sys/un.h> +#include <sys/types.h> +#include <unistd.h> +#include "cext.h" #include "ixp.h" -#include <cext.h> +static unsigned char msg[IXP_MAX_MSG]; -static size_t offsets[MAX_CONN * MAX_OPEN_FILES][2]; /* set of possible fd's */ - -static void check_error(IXPClient * c, void *msg) -{ - ResHeader h; - - if (c->errstr) - free(c->errstr); - c->errstr = 0; - - memcpy(&h, msg, sizeof(ResHeader)); - if (h.res == RERROR) - c->errstr = strdup((char *) msg + sizeof(ResHeader)); -} - -static void handle_dead_server(IXPClient * c) -{ - if (c->errstr) - free(c->errstr); - c->errstr = strdup(DEAD_SERVER); - if (c->fd) { - shutdown(c->fd, SHUT_RDWR); - close(c->fd); - } - c->fd = -1; -} - -static void *poll_server(IXPClient * c, void *request, size_t req_len, - size_t * out_len) -{ - size_t num = 0; - void *result = 0; - int r, header = 0; - - if (c->errstr) - free(c->errstr); - c->errstr = 0; - - /* first send request */ - while (num < req_len) { - FD_ZERO(&c->wr); - FD_SET(c->fd, &c->wr); - r = select(c->fd + 1, 0, &c->wr, 0, 0); - if (r == -1 && errno == EINTR) - continue; - if (r < 0) { - perror("ixp: client: select"); - if (result) - free(result); - handle_dead_server(c); - return 0; - } else if (r > 0) { - if (!header) { - /* write header first */ - r = write(c->fd, &req_len, sizeof(size_t)); - if (r != sizeof(size_t)) { - if (result) - free(result); - handle_dead_server(c); - return 0; - } - header = 1; - } - r = write(c->fd, ((char *) request) + num, req_len - num); - if (r < 1) { - perror("ixp: client: write"); - if (result) - free(result); - handle_dead_server(c); - return 0; - } - num += r; - } - } - free(request); /* cleanup */ - - num = 0; - header = 0; - /* now wait for response */ - do { - FD_ZERO(&c->rd); - FD_SET(c->fd, &c->rd); - r = select(c->fd + 1, &c->rd, 0, 0, 0); - if (r == -1 && errno == EINTR) - continue; - if (r < 0) { - perror("ixp: client: select"); - if (result) - free(result); - handle_dead_server(c); - return 0; - } else if (r > 0) { - if (!header) { - r = read(c->fd, out_len, sizeof(size_t)); - if (r != sizeof(size_t)) { - if (result) - free(result); - handle_dead_server(c); - return 0; - } - result = cext_emallocz(*out_len); - header = 1; - } - r = read(c->fd, ((char *) result) + num, *out_len - num); - if (r < 1) { - perror("ixp: client: read"); - if (result) - free(result); - handle_dead_server(c); - return 0; - } - num += r; - } - } - while (num != *out_len); - - /* error checking */ - if (result) - check_error(c, result); - if (c->errstr) { - free(result); - result = 0; - } - return result; -} - -static void cixp_create(IXPClient * c, char *path) +static int +do_fcall(IXPClient * c) { - ResHeader h; - size_t req_len, res_len; - void *req = tcreate_message(path, &req_len); - void *result = poll_server(c, req, req_len, &res_len); - - if (!result) - return; - memcpy(&h, result, sizeof(ResHeader)); - free(result); + unsigned int msize = ixp_fcall_to_msg(&c->fcall, msg, IXP_MAX_MSG); + c->errstr = 0; + if(ixp_send_message(c->fd, msg, msize, &c->errstr) != msize) + return -1; + if(!ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &c->errstr)) + return -1; + if(!(msize = ixp_msg_to_fcall(msg, IXP_MAX_MSG, &c->fcall))) { + c->errstr = "received bad message"; + return -1; + } + if(c->fcall.id == RERROR) { + c->errstr = c->fcall.errstr; + return -1; + } + return 0; } -static int cixp_open(IXPClient * c, char *path) +int +ixp_client_init(IXPClient * c, char *sockfile) { - ResHeader h; - size_t req_len, res_len; - void *req = topen_message(path, &req_len); - void *result = poll_server(c, req, req_len, &res_len); - - if (!result) - return -1; - memcpy(&h, result, sizeof(ResHeader)); - free(result); - offsets[h.fd][0] = offsets[h.fd][1] = 0; - return h.fd; + if((c->fd = ixp_connect_sock(sockfile)) < 0) { + c->errstr = "cannot connect server"; + return -1; + } + /* version */ + c->fcall.id = TVERSION; + c->fcall.tag = IXP_NOTAG; + c->fcall.maxmsg = IXP_MAX_MSG; + cext_strlcpy(c->fcall.version, IXP_VERSION, sizeof(c->fcall.version)); + if(do_fcall(c) == -1) { + ixp_client_deinit(c); + return -1; + } + if(strncmp(c->fcall.version, IXP_VERSION, strlen(IXP_VERSION))) { + c->errstr = "9P versions differ"; + ixp_client_deinit(c); + return -1; /* we cannot handle this version */ + } + c->root_fid = getpid(); + + /* attach */ + c->fcall.id = TATTACH; + c->fcall.tag = IXP_NOTAG; + c->fcall.fid = c->root_fid; + c->fcall.afid = IXP_NOFID; + cext_strlcpy(c->fcall.uname, getenv("USER"), sizeof(c->fcall.uname)); + c->fcall.aname[0] = 0; + if(do_fcall(c) == -1) { + ixp_client_deinit(c); + return -1; + } + c->root_qid = c->fcall.qid; + return 0; } -static size_t -cixp_read(IXPClient * c, int fd, void *out_buf, size_t out_buf_len) +int +ixp_client_remove(IXPClient * c, unsigned int newfid, char *filepath) { - size_t len; - - len = seek_read(c, fd, offsets[fd][0], out_buf, out_buf_len); - if (c->errstr) - return 0; - if (len == out_buf_len) - offsets[fd][0] += len; - return len; + if(ixp_client_walk(c, newfid, filepath) == -1) + return -1; + /* remove */ + c->fcall.id = TREMOVE; + c->fcall.tag = IXP_NOTAG; + c->fcall.fid = newfid; + return do_fcall(c); } -size_t -seek_read(IXPClient * c, int fd, size_t offset, - void *out_buf, size_t out_buf_len) +int +ixp_client_create(IXPClient * c, unsigned int dirfid, char *name, + unsigned int perm, unsigned char mode) { - ResHeader h; - size_t req_len, res_len; - void *req = tread_message(fd, offset, out_buf_len, &req_len); - void *result = poll_server(c, req, req_len, &res_len); - - if (!result) - return -1; - memcpy(&h, result, sizeof(ResHeader)); - memcpy(out_buf, ((char *) result) + sizeof(ResHeader), h.buf_len); - free(result); - return h.buf_len; + /* create */ + c->fcall.id = TCREATE; + c->fcall.tag = IXP_NOTAG; + c->fcall.fid = dirfid; + cext_strlcpy(c->fcall.name, name, sizeof(c->fcall.name)); + c->fcall.perm = perm; + c->fcall.mode = mode; + return do_fcall(c); } -static void cixp_write(IXPClient * c, int fd, void *content, size_t in_len) +int +ixp_client_walk(IXPClient * c, unsigned int newfid, char *filepath) { - seek_write(c, fd, offsets[fd][1], content, in_len); - if (!c->errstr) - offsets[fd][1] += in_len; + unsigned int i; + char *wname[IXP_MAX_WELEM]; + /* walk */ + c->fcall.id = TWALK; + c->fcall.fid = c->root_fid; + c->fcall.newfid = newfid; + if(filepath) { + cext_strlcpy(c->fcall.name, filepath, sizeof(c->fcall.name)); + c->fcall.nwname = + cext_tokenize(wname, IXP_MAX_WELEM, c->fcall.name, '/'); + for(i = 0; i < c->fcall.nwname; i++) + cext_strlcpy(c->fcall.wname[i], wname[i], sizeof(c->fcall.wname[i])); + } + return do_fcall(c); } -void -seek_write(IXPClient * c, int fd, size_t offset, void *content, - size_t in_len) +int +ixp_client_open(IXPClient * c, unsigned int newfid, char *filepath, + unsigned char mode) { - ResHeader h; - size_t req_len, res_len; - void *req = twrite_message(fd, offset, content, in_len, &req_len); - void *result = poll_server(c, req, req_len, &res_len); - - if (!result) - return; - memcpy(&h, result, sizeof(ResHeader)); - free(result); + if(ixp_client_walk(c, newfid, filepath) == -1) + return -1; + + /* open */ + c->fcall.id = TOPEN; + c->fcall.tag = IXP_NOTAG; + c->fcall.fid = newfid; + c->fcall.mode = mode; + return do_fcall(c); } -static void cixp_close(IXPClient * c, int fd) +int +ixp_client_read(IXPClient * c, unsigned int fid, unsigned long long offset, + void *result, unsigned int res_len) { - ResHeader h; - size_t req_len, res_len; - void *req = tclose_message(fd, &req_len); - void *result = poll_server(c, req, req_len, &res_len); - - if (!result) - return; - memcpy(&h, result, sizeof(ResHeader)); - free(result); - offsets[fd][0] = offsets[fd][1] = 0; + unsigned int bytes = c->fcall.iounit; + + /* read */ + c->fcall.id = TREAD; + c->fcall.tag = IXP_NOTAG; + c->fcall.fid = fid; + c->fcall.offset = offset; + c->fcall.count = res_len < bytes ? res_len : bytes; + if(do_fcall(c) == -1) + return -1; + memcpy(result, c->fcall.data, c->fcall.count); + return c->fcall.count; } -static void cixp_remove(IXPClient * c, char *path) +int +ixp_client_write(IXPClient * c, unsigned int fid, + unsigned long long offset, unsigned int count, + unsigned char *data) { - ResHeader h; - size_t req_len, res_len; - void *req = tremove_message(path, &req_len); - void *result = poll_server(c, req, req_len, &res_len); - - if (!result) - return; - memcpy(&h, result, sizeof(ResHeader)); - free(result); + if(count > c->fcall.iounit) + { + c->errstr = "iounit exceeded"; + return -1; + } + /* write */ + c->fcall.id = TWRITE; + c->fcall.tag = IXP_NOTAG; + c->fcall.fid = fid; + c->fcall.offset = offset; + c->fcall.count = count; + memcpy(c->fcall.data, data, count); + if(do_fcall(c) == -1) + return -1; + return c->fcall.count; } -IXPClient *init_ixp_client(char *sockfile) +int +ixp_client_close(IXPClient * c, unsigned int fid) { - struct sockaddr_un addr = { 0 }; - socklen_t su_len; - - /* init */ - IXPClient *c = (IXPClient *) cext_emallocz(sizeof(IXPClient)); - c->create = cixp_create; - c->open = cixp_open; - c->read = cixp_read; - c->write = cixp_write; - c->close = cixp_close; - c->remove = cixp_remove; - - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sockfile, sizeof(addr.sun_path)); - su_len = sizeof(struct sockaddr) + strlen(addr.sun_path); - - if ((c->fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - free(c); - return 0; - } - if (connect(c->fd, (struct sockaddr *) &addr, su_len)) { - close(c->fd); - free(c); - return 0; - } - return c; + /* clunk */ + c->fcall.id = TCLUNK; + c->fcall.tag = IXP_NOTAG; + c->fcall.fid = fid; + return do_fcall(c); } -void deinit_client(IXPClient * c) +void +ixp_client_deinit(IXPClient * c) { - if (c->fd) { - shutdown(c->fd, SHUT_RDWR); - close(c->fd); - } - c->fd = -1; - free(c); + /* session finished, now shutdown */ + if(c->fd) { + shutdown(c->fd, SHUT_RDWR); + close(c->fd); + } } diff --git a/libixp/convert.c b/libixp/convert.c @@ -0,0 +1,197 @@ +/* + * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> + * See LICENSE file for license details. + */ + +#include <stdlib.h> +#include <string.h> +#include "ixp.h" + +/* encode/decode stuff */ + +void * +ixp_enc_u8(unsigned char *msg, unsigned char val) +{ + msg[0] = val; + return &msg[1]; +} + +void * +ixp_dec_u8(unsigned char *msg, unsigned char *val) +{ + *val = msg[0]; + return &msg[1]; +} + +void * +ixp_enc_u16(unsigned char *msg, unsigned short val) +{ + msg[0] = val; + msg[1] = val >> 8; + return &msg[2]; +} + +void * +ixp_dec_u16(unsigned char *msg, unsigned short *val) +{ + *val = msg[0] | (msg[1] << 8); + return &msg[2]; +} + +void * +ixp_enc_u32(unsigned char *msg, unsigned int val) +{ + msg[0] = val; + msg[1] = val >> 8; + msg[2] = val >> 16; + msg[3] = val >> 24; + return &msg[4]; +} + +void * +ixp_dec_u32(unsigned char *msg, unsigned int *val) +{ + *val = msg[0] | (msg[1] << 8) | (msg[2] << 16) | (msg[3] << 24); + return &msg[4]; +} + +void * +ixp_enc_u64(unsigned char *msg, unsigned long long val) +{ + msg[0] = val; + msg[1] = val >> 8; + msg[2] = val >> 16; + msg[3] = val >> 24; + msg[4] = val >> 32; + msg[5] = val >> 40; + msg[6] = val >> 48; + msg[7] = val >> 56; + return &msg[8]; +} + +void * +ixp_dec_u64(unsigned char *msg, unsigned long long *val) +{ + *val = + (unsigned long long) msg[0] | ((unsigned long long) msg[1] << 8) | + ((unsigned long long) msg[2] << 16) | ((unsigned long long) msg[3] + << 24) | ((unsigned long + long) msg[4] << + 32) | ((unsigned + long long) + msg[5] << + 40) | + ((unsigned long long) msg[6] << 48) | ((unsigned long long) msg[7] + << 56); + return &msg[8]; +} + +void * +ixp_enc_string(unsigned char *msg, const char *s) +{ + unsigned short len = s ? strlen(s) : 0; + msg = ixp_enc_u16(msg, len); + if(s) + memcpy(msg, s, len); + return &msg[len]; +} + +void * +ixp_dec_string(unsigned char *msg, char *string, unsigned short stringlen, + unsigned short *len) +{ + msg = ixp_dec_u16(msg, len); + if(!(*len)) + return msg; + if(*len > stringlen - 1) + /* might never happen if stringlen == IXP_MAX_MSG */ + string[0] = 0; + else { + memcpy(string, msg, *len); + string[*len] = 0; + } + return &msg[*len]; +} + +void * +ixp_enc_data(unsigned char *msg, unsigned char *data, unsigned int datalen) +{ + memcpy(msg, data, datalen); + return &msg[datalen]; +} + +void * +ixp_dec_data(unsigned char *msg, unsigned char *data, unsigned int datalen) +{ + memcpy(data, msg, datalen); + return &msg[datalen]; +} + +void * +ixp_enc_prefix(unsigned char *msg, unsigned int size, unsigned char id, + unsigned short tag) +{ + msg = ixp_enc_u32(msg, size); + msg = ixp_enc_u8(msg, id); + return ixp_enc_u16(msg, tag); +} + +void * +ixp_dec_prefix(unsigned char *msg, unsigned int *size, unsigned char *id, + unsigned short *tag) +{ + msg = ixp_dec_u32(msg, size); + msg = ixp_dec_u8(msg, id); + return ixp_dec_u16(msg, tag); +} + +void * +ixp_enc_qid(unsigned char *msg, Qid * qid) +{ + msg = ixp_enc_u8(msg, qid->type); + msg = ixp_enc_u32(msg, qid->version); + return ixp_enc_u64(msg, qid->path); +} + +void * +ixp_dec_qid(unsigned char *msg, Qid * qid) +{ + msg = ixp_dec_u8(msg, &qid->type); + msg = ixp_dec_u32(msg, &qid->version); + return ixp_dec_u64(msg, &qid->path); +} + +void * +ixp_enc_stat(unsigned char *msg, Stat * stat) +{ + msg = ixp_enc_u16(msg, ixp_sizeof_stat(stat) - sizeof(unsigned short)); + msg = ixp_enc_u16(msg, stat->type); + msg = ixp_enc_u32(msg, stat->dev); + msg = ixp_enc_qid(msg, &stat->qid); + msg = ixp_enc_u32(msg, stat->mode); + msg = ixp_enc_u32(msg, stat->atime); + msg = ixp_enc_u32(msg, stat->mtime); + msg = ixp_enc_u64(msg, stat->length); + msg = ixp_enc_string(msg, stat->name); + msg = ixp_enc_string(msg, stat->uid); + msg = ixp_enc_string(msg, stat->gid); + return ixp_enc_string(msg, stat->muid); +} + +void * +ixp_dec_stat(unsigned char *msg, Stat * stat) +{ + unsigned short dummy; + msg += sizeof(unsigned short); + msg = ixp_dec_u16(msg, &stat->type); + msg = ixp_dec_u32(msg, &stat->dev); + msg = ixp_dec_qid(msg, &stat->qid); + msg = ixp_dec_u32(msg, &stat->mode); + msg = ixp_dec_u32(msg, &stat->atime); + msg = ixp_dec_u32(msg, &stat->mtime); + msg = ixp_dec_u64(msg, &stat->length); + msg = ixp_dec_string(msg, stat->name, sizeof(stat->name), &dummy); + msg = ixp_dec_string(msg, stat->uid, sizeof(stat->uid), &dummy); + msg = ixp_dec_string(msg, stat->gid, sizeof(stat->gid), &dummy); + return ixp_dec_string(msg, stat->muid, sizeof(stat->muid), &dummy); +} diff --git a/libixp/ixp.h b/libixp/ixp.h @@ -1,172 +1,289 @@ /* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. + *(C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> + *See LICENSE file for license details. */ #include <sys/types.h> -#include <sys/time.h> -#include <unistd.h> -#define MAX_CONN 32 -#define MAX_OPEN_FILES 16 -#define DEAD_SERVER "server closed connection unexpectedly" -#define MAX_SEEN_SHUTDOWN 3 +#ifndef nil +#define nil 0 +#endif -#define xMAX(x,y) ((x) > (y) ? (x) : (y)) +#define IXP_VERSION "9P2000" +#define IXP_MAX_VERSION 32 +#define IXP_MAX_ERROR 128 +#define IXP_MAX_CACHE 32 +#define IXP_MAX_MSG 8192 +#define IXP_MAX_FLEN 128 +#define IXP_MAX_ULEN 32 +#define IXP_MAX_STAT 64 +#define IXP_MAX_WELEM 16 /*MAXWELEM */ +#define IXP_MAX_TFUNCS 14 -/* 9P message types */ + +/* + size[4] Tversion tag[2] msize[4] version[s] + size[4] Rversion tag[2] msize[4] version[s] + size[4] Tauth tag[2] afid[4] uname[s] aname[s] + size[4] Rauth tag[2] aqid[13] + size[4] Rerror tag[2] ename[s] + size[4] Tflush tag[2] oldtag[2] + size[4] Rflush tag[2] + size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] + size[4] Rattach tag[2] qid[13] + size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) + size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13]) + size[4] Topen tag[2] fid[4] mode[1] + size[4] Ropen tag[2] qid[13] iounit[4] + size[4] Tcreate tag[2] fid[4] name[s] perm[4] mode[1] + size[4] Rcreate tag[2] qid[13] iounit[4] + size[4] Tread tag[2] fid[4] offset[8] count[4] + size[4] Rread tag[2] count[4] data[count] + size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] + size[4] Rwrite tag[2] count[4] + size[4] Tclunk tag[2] fid[4] + size[4] Rclunk tag[2] + size[4] Tremove tag[2] fid[4] + size[4] Rremove tag[2] + size[4] Tstat tag[2] fid[4] + size[4] Rstat tag[2] stat[n] + size[4] Twstat tag[2] fid[4] stat[n] + size[4] Rwstat tag[2] + + stat[n]: + size[2] total byte count of the following data + type[2] for kernel use + dev[4] for kernel use + qid.type[1] the type of the file (directory, etc.), + represented as a bit vector corresponding to the high 8 bits of the file's mode word. + qid.vers[4] version number for given path + qid.path[8] the file server's unique identification for the file + mode[4] permissions and flags + atime[4] last access time + mtime[4] last modification time + length[8] length of file in bytes + name[ s ] file name; must be / if the file is the root directory of the server + uid[ s ] owner name + gid[ s ] group name + muid[ s ] +*/ + +/*9P message types */ enum { - TVERSION = 100, - RVERSION, - TAUTH = 102, - RAUTH, - TATTACH = 104, - RATTACH, - TERROR = 106, - RERROR, - TFLUSH = 108, - RFLUSH, - TWALK = 110, - RWALK, - TOPEN = 112, - ROPEN, - TCREATE = 114, - RCREATE, - TREAD = 116, - RREAD, - TWRITE = 118, - RWRITE, - TCLUNK = 120, - RCLUNK, - TREMOVE = 122, - RREMOVE, - TSTAT = 124, - RSTAT, - TWSTAT = 126, - RWSTAT, + TVERSION = 100, + RVERSION, + TAUTH = 102, + RAUTH, + TATTACH = 104, + RATTACH, + TERROR = 106, + RERROR, + TFLUSH = 108, + RFLUSH, + TWALK = 110, + RWALK, + TOPEN = 112, + ROPEN, + TCREATE = 114, + RCREATE, + TREAD = 116, + RREAD, + TWRITE = 118, + RWRITE, + TCLUNK = 120, + RCLUNK, + TREMOVE = 122, + RREMOVE, + TSTAT = 124, + RSTAT, + TWSTAT = 126, + RWSTAT, }; -typedef struct ResHeader ResHeader; -typedef struct ReqHeader ReqHeader; -typedef struct Connection Connection; -typedef struct File File; -typedef struct IXPClient IXPClient; -typedef struct IXPServer IXPServer; -typedef int IXPRequest; -typedef int IXPResponse; -typedef enum { - HALT, SHUTDOWN, RUNNING -} IXPRunlevel; - -struct ReqHeader { - IXPRequest req; - int fd; - size_t offset; - size_t buf_len; -}; +/*borrowed from libc.h of Plan 9 */ +#define DMDIR 0x80000000 /*mode bit for directories */ +#define DMAPPEND 0x40000000 /*mode bit for append only files */ +#define DMEXCL 0x20000000 /*mode bit for exclusive use files */ +#define DMMOUNT 0x10000000 /*mode bit for mounted channel */ +#define DMAUTH 0x08000000 /*mode bit for authentication file */ +#define DMTMP 0x04000000 /*mode bit for non-backed-up file */ + +#define DMREAD 0x4<<6 /*mode bit for read permission */ +#define DMWRITE 0x2<<6 /*mode bit for write permission */ +#define DMEXEC 0x1<<6 /*mode bit for execute permission */ -struct ResHeader { - IXPResponse res; - int fd; - size_t buf_len; +/*modes */ +enum { + IXP_OREAD = 0x00, + IXP_OWRITE = 0x01, + IXP_ORDWR = 0x02, + IXP_OEXEC = 0x03, + IXP_OEXCL = 0x04, + IXP_OTRUNC = 0x10, + IXP_OREXEC = 0x20, + IXP_ORCLOSE = 0x40, + IXP_OAPPEND = 0x80, }; -/** Definition of a connection to IXP */ -struct Connection { - IXPServer *s; /* !< server for this connection */ - int index; /* !< index inside server */ - int fd; /* !< file descriptor */ - int mode; /* 0 for reading, 1 for writing */ - int header; - void *data; - size_t len; - size_t remain; - void (*read) (Connection *); - void (*write) (Connection *); - File *files[MAX_OPEN_FILES]; - int seen[MAX_OPEN_FILES]; +/*qid.types */ +enum { + IXP_QTDIR = 0x80, + IXP_QTAPPEND = 0x40, + IXP_QTEXCL = 0x20, + IXP_QTMOUNT = 0x10, + IXP_QTAUTH = 0x08, + IXP_QTTMP = 0x04, + IXP_QTSYMLINK = 0x02, + IXP_QTLINK = 0x01, + IXP_QTFILE = 0x00, }; -struct File { - char *name; - void *content; - size_t size; - int bind; - File *parent; - File *next; - /* introduced IXPServer in signature for IXPServer->errstr */ - void (*after_write) (IXPServer * s, File *); - void (*before_read) (IXPServer * s, File *); +#define IXP_NOTAG (unsigned short)~0U /*Dummy tag */ +#define IXP_NOFID (unsigned int)~0 /*No auth */ + +typedef struct { + unsigned char type; + unsigned int version; + unsigned long long path; +} Qid; + +/*stat structure */ +typedef struct { + unsigned short type; + unsigned int dev; + Qid qid; + unsigned int mode; + unsigned int atime; + unsigned int mtime; + unsigned long long length; + char name[IXP_MAX_FLEN]; + char uid[IXP_MAX_ULEN]; + char gid[IXP_MAX_ULEN]; + char muid[IXP_MAX_ULEN]; +} Stat; + +typedef struct { + unsigned char id; + unsigned short tag; + unsigned int fid; + unsigned int maxmsg; /*Tversion, Rversion */ + char version[IXP_MAX_VERSION]; /*Tversion, Rversion */ + unsigned short oldtag; /*Tflush */ + char errstr[IXP_MAX_ERROR]; /*Rerror */ + Qid qid; /*Rattach, Ropen, Rcreate */ + unsigned int iounit; /*Ropen, Rcreate */ + Qid aqid; /*Rauth */ + unsigned int afid; /*Tauth, Tattach */ + char uname[IXP_MAX_ULEN]; /*Tauth, Tattach */ + char aname[IXP_MAX_FLEN]; /*Tauth, Tattach */ + unsigned int perm; /*Tcreate */ + char name[IXP_MAX_FLEN]; /*Tcreate */ + unsigned char mode; /*Tcreate, Topen */ + unsigned int newfid; /*Twalk */ + unsigned short nwname; /*Twalk */ + char wname[IXP_MAX_WELEM][IXP_MAX_FLEN]; /*Twalk */ + unsigned short nwqid; /*Rwalk */ + Qid wqid[IXP_MAX_WELEM]; /*Rwalk */ + unsigned long long offset; /*Tread, Twrite */ + unsigned int count; /*Tread, Twrite, Rread */ + Stat stat; /*Rstat */ + unsigned short nstat; /*Twstat, Rstat */ + unsigned char data[IXP_MAX_MSG]; /*Twrite, Rread, Twstat, + *Rstat */ +} Fcall; + +typedef struct IXPServer IXPServer; +typedef struct IXPConn IXPConn; +typedef struct IXPMap IXPMap; + +struct IXPMap { + unsigned int fid; + Qid qid; }; -struct IXPClient { - int fd; - fd_set rd, wr; - char *errstr; /* 0 if succes, CHECK AFTER EACH of following - * operations */ - /* returns fd if path exists */ - void (*create) (IXPClient *, char *path); - void (*remove) (IXPClient *, char *path); - int (*open) (IXPClient *, char *path); - void (*close) (IXPClient *, int fd); - size_t(*read) (IXPClient *, int fd, void *out_buf, size_t out_buf_len); - void (*write) (IXPClient *, int fd, void *content, size_t in_len); +struct IXPConn { + int fd; + void (*read) (IXPServer *, IXPConn *); + void (*close) (IXPServer *, IXPConn *); + IXPMap **map; + size_t mapsz; + Fcall *fcall; + Fcall **pend; + size_t pendsz; }; struct IXPServer { - char *sockfile; - IXPRunlevel runlevel; - Connection conn[MAX_CONN]; - fd_set rd, wr; /* socks to wakeup while select() */ - int nfds; /* number of file descriptors */ - File *root; - char *errstr; /* 0 if succes, CHECK AFTER EACH of following - * operations */ - File *(*create) (IXPServer *, char *); - File *(*open) (IXPServer *, char *); - size_t(*read) (IXPServer *, int, size_t, void *, size_t); - void (*write) (IXPServer *, int, size_t, void *, size_t); - void (*close) (IXPServer *, int); - void (*remove) (IXPServer *, char *); + int running; + IXPConn **conn; + size_t connsz; + int maxfd; + fd_set rd; }; -/* client.c, implements client stub functions for fs access */ -IXPClient *init_ixp_client(char *sockfile); -void deinit_client(IXPClient * c); -size_t seek_read(IXPClient * c, int fd, size_t offset, void *out_buf, size_t out_buf_len); -void seek_write(IXPClient * c, int fd, size_t offset, void *content, size_t in_len); +typedef struct { + int fd; + unsigned int root_fid; + Qid root_qid; + Fcall fcall; + char *errstr; +} IXPClient; + +/* client.c */ +int ixp_client_init(IXPClient *c, char *address); +void ixp_client_deinit(IXPClient *c); +int ixp_client_remove(IXPClient *c, unsigned int newfid, char *filepath); +int ixp_client_create(IXPClient *c, unsigned int dirfid, char *name, + unsigned int perm, unsigned char mode); +int ixp_client_walk(IXPClient *c, unsigned int newfid, char *filepath); +int ixp_client_open(IXPClient *c, unsigned int newfid, char *filepath, + unsigned char mode); +int ixp_client_read(IXPClient *c, unsigned int fid, + unsigned long long offset, void *result, + unsigned int res_len); +int ixp_client_write(IXPClient *c, unsigned int fid, + unsigned long long offset, + unsigned int count, unsigned char *data); +int ixp_client_close(IXPClient *c, unsigned int fid); + +/* convert.c */ +void *ixp_enc_u8(unsigned char *msg, unsigned char val); +void *ixp_dec_u8(unsigned char *msg, unsigned char *val); +void *ixp_enc_u16(unsigned char *msg, unsigned short val); +void *ixp_dec_u16(unsigned char *msg, unsigned short *val); +void *ixp_enc_u32(unsigned char *msg, unsigned int val); +void *ixp_dec_u32(unsigned char *msg, unsigned int *val); +void *ixp_enc_u64(unsigned char *msg, unsigned long long val); +void *ixp_dec_u64(unsigned char *msg, unsigned long long *val); +void *ixp_enc_string(unsigned char *msg, const char *s); +void *ixp_dec_string(unsigned char *msg, char *string, + unsigned short stringlen, unsigned short *len); +void *ixp_enc_data(unsigned char *msg, unsigned char *data, + unsigned int datalen); +void *ixp_dec_data(unsigned char *msg, unsigned char *data, + unsigned int datalen); +void *ixp_enc_prefix(unsigned char *msg, unsigned int size, + unsigned char id, unsigned short tag); +void *ixp_dec_prefix(unsigned char *msg, unsigned int *size, + unsigned char *id, unsigned short *tag); +void *ixp_enc_qid(unsigned char *msg, Qid *qid); +void *ixp_dec_qid(unsigned char *msg, Qid *qid); +void *ixp_enc_stat(unsigned char *msg, Stat *stat); +void *ixp_dec_stat(unsigned char *msg, Stat *stat); /* message.c */ -void *tcreate_message(char *path, size_t * msg_len); -void *topen_message(char *path, size_t * msg_len); -void *tread_message(int fd, size_t offset, size_t buf_len, size_t * msg_len); -void *twrite_message(int fd, size_t offset, void *msg, size_t in_len, size_t * msg_len); -void *tclose_message(int fd, size_t * msg_len); -void *tremove_message(char *path, size_t * msg_len); -void *rcreate_message(size_t * msg_len); -void *ropen_message(int fd, size_t * msg_len); -void *rread_message(void *content, size_t content_len, size_t * msg_len); -void *rwrite_message(size_t * msg_len); -void *rclose_message(size_t * msg_len); -void *rremove_message(size_t * msg_len); -void *rerror_message(char *errstr, size_t * msg_len); - -/* ramfs.c */ -int is_directory(File * f); -File *ixp_walk(IXPServer * s, char *path); -File *ixp_create(IXPServer * s, char *path); -File *ixp_open(IXPServer * s, char *path); -size_t ixp_read(IXPServer * s, int fd, size_t offset, void *out_buf, size_t out_buf_len); -void ixp_write(IXPServer * s, int fd, size_t offset, void *content, size_t in_len); -void ixp_close(IXPServer * s, int fd); -void ixp_remove(IXPServer * s, char *path); -void ixp_remove_file(IXPServer * s, File * f); - -/* server.c, uses fs directly for manipulation */ -IXPServer *init_server(char *sockfile, void (*cleanup) (void)); -void deinit_server(IXPServer * s); -File *fd_to_file(IXPServer * s, int fd); -void run_server(IXPServer * s); -void run_server_with_fd_support(IXPServer * s, int fd, void (*fd_read) (Connection *), /* callback for read on fd */ - void (*fd_write) (Connection *)); /* callback for write on fd */ -void set_error(IXPServer * s, char *errstr); +unsigned short ixp_sizeof_stat(Stat *stat); +unsigned int ixp_fcall_to_msg(Fcall *fcall, void *msg, unsigned int msglen); +unsigned int ixp_msg_to_fcall(void *msg, unsigned int msglen, Fcall *fcall); + +/* server.c */ +char *ixp_server_loop(IXPServer *s); +IXPMap *ixp_server_fid2map(IXPConn *c, unsigned int fid); + +/* socket.c */ +int ixp_connect_sock(char *address); +int ixp_accept_sock(int fd); +int ixp_create_sock(char *address, char **errstr); + +/* transport.c */ +unsigned int ixp_send_message(int fd, void *msg, unsigned int msize, char **errstr); +unsigned int ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr); diff --git a/libixp/message.c b/libixp/message.c @@ -3,170 +3,315 @@ * See LICENSE file for license details. */ +#include <stdio.h> #include <stdlib.h> #include <string.h> - #include "ixp.h" -#include <cext.h> +#define IXP_QIDSZ (sizeof(unsigned char) + sizeof(unsigned int)\ + + sizeof(unsigned long long)) -void *tcreate_message(char *path, size_t * msg_len) +static unsigned short +sizeof_string(const char *s) { - char *msg; - ReqHeader h; - *msg_len = sizeof(ReqHeader) + strlen(path) + 1; - msg = cext_emallocz(*msg_len); - h.req = TCREATE; - memcpy(msg, &h, sizeof(ReqHeader)); - memcpy(msg + sizeof(ReqHeader), path, strlen(path) + 1); - return msg; + return sizeof(unsigned short) + strlen(s); } -void *topen_message(char *path, size_t * msg_len) +unsigned short +ixp_sizeof_stat(Stat * stat) { - char *msg; - ReqHeader h; - *msg_len = sizeof(ReqHeader) + strlen(path) + 1; - msg = cext_emallocz(*msg_len); - h.req = TOPEN; - memcpy(msg, &h, sizeof(ReqHeader)); - memcpy(msg + sizeof(ReqHeader), path, strlen(path) + 1); - return msg; + return IXP_QIDSZ + + 2 * sizeof(unsigned short) + + 4 * sizeof(unsigned int) + + sizeof(unsigned long long) + + sizeof_string(stat->name) + + sizeof_string(stat->uid) + + sizeof_string(stat->gid) + + sizeof_string(stat->muid); } -void *tread_message(int fd, size_t offset, size_t buf_len, - size_t * msg_len) +unsigned int +ixp_fcall_to_msg(Fcall * fcall, void *msg, unsigned int msglen) { - char *msg; - ReqHeader h; - *msg_len = sizeof(ReqHeader); - msg = cext_emallocz(*msg_len); - h.req = TREAD; - h.fd = fd; - h.offset = offset; - h.buf_len = buf_len; - memcpy(msg, &h, sizeof(ReqHeader)); - return msg; -} - -void *twrite_message(int fd, size_t offset, void *content, - size_t content_len, size_t * msg_len) -{ - char *msg; - ReqHeader h; - *msg_len = sizeof(ReqHeader) + content_len; - msg = cext_emallocz(*msg_len); - h.req = TWRITE; - h.fd = fd; - h.offset = offset; - h.buf_len = content_len; - memcpy(msg, &h, sizeof(ReqHeader)); - memcpy(msg + sizeof(ReqHeader), content, content_len); - return msg; -} + unsigned int i, msize = + sizeof(unsigned char) + sizeof(unsigned short) + + sizeof(unsigned int); + void *p = msg; -void *tclose_message(int fd, size_t * msg_len) -{ - char *msg; - ReqHeader h; - *msg_len = sizeof(ReqHeader); - msg = cext_emallocz(*msg_len); - h.req = TCLUNK; - h.fd = fd; - memcpy(msg, &h, sizeof(ReqHeader)); - return msg; -} + switch (fcall->id) { + case TVERSION: + case RVERSION: + msize += sizeof(unsigned int) + sizeof_string(fcall->version); + break; + case TAUTH: + msize += + sizeof(unsigned int) + sizeof_string(fcall->uname) + + sizeof_string(fcall->aname); + break; + case RAUTH: + case RATTACH: + msize += IXP_QIDSZ; + break; + case TATTACH: + msize += + 2 * sizeof(unsigned int) + sizeof_string(fcall->uname) + + sizeof_string(fcall->aname); + break; + case RERROR: + msize += sizeof_string(fcall->errstr); + break; + case RWRITE: + case TCLUNK: + case TREMOVE: + case TSTAT: + msize += sizeof(unsigned int); + break; + case TWALK: + msize += sizeof(unsigned short) + 2 * sizeof(unsigned int); + for(i = 0; i < fcall->nwname; i++) + msize += sizeof_string(fcall->wname[i]); + break; + case TFLUSH: + msize += sizeof(unsigned short); + break; + case RWALK: + msize += sizeof(unsigned short) + fcall->nwqid * IXP_QIDSZ; + break; + case TOPEN: + msize += sizeof(unsigned int) + sizeof(unsigned char); + break; + case ROPEN: + case RCREATE: + msize += IXP_QIDSZ + sizeof(unsigned int); + break; + case TCREATE: + msize += + sizeof(unsigned char) + 2 * sizeof(unsigned int) + + sizeof_string(fcall->name); + break; + case TREAD: + msize += 2 * sizeof(unsigned int) + sizeof(unsigned long long); + break; + case RREAD: + msize += sizeof(unsigned int) + fcall->count; + break; + case TWRITE: + msize += + 2 * sizeof(unsigned int) + sizeof(unsigned long long) + + fcall->count; + break; + case RSTAT: + msize += sizeof(unsigned short) + ixp_sizeof_stat(&fcall->stat); + break; + case TWSTAT: + msize += sizeof(unsigned int) + sizeof(unsigned short) + ixp_sizeof_stat(&fcall->stat); + break; + default: + break; + } -void *tremove_message(char *path, size_t * msg_len) -{ - char *msg; - ReqHeader h; - *msg_len = sizeof(ReqHeader) + strlen(path) + 1; - msg = cext_emallocz(*msg_len); - h.req = TREMOVE; - memcpy(msg, &h, sizeof(ReqHeader)); - memcpy(msg + sizeof(ReqHeader), path, strlen(path) + 1); - return msg; -} + if(msize > msglen) + return 0; + p = ixp_enc_prefix(p, msize, fcall->id, fcall->tag); -void *rcreate_message(size_t * msg_len) -{ - char *msg; - ResHeader h; - *msg_len = sizeof(ResHeader); - msg = cext_emallocz(*msg_len); - h.res = RCREATE; - memcpy(msg, &h, sizeof(ResHeader)); - return msg; -} + switch (fcall->id) { + case TVERSION: + case RVERSION: + p = ixp_enc_u32(p, fcall->maxmsg); + p = ixp_enc_string(p, fcall->version); + break; + case TAUTH: + p = ixp_enc_u32(p, fcall->afid); + p = ixp_enc_string(p, fcall->uname); + p = ixp_enc_string(p, fcall->aname); + break; + case RAUTH: + p = ixp_enc_qid(p, &fcall->aqid); + break; + case RATTACH: + p = ixp_enc_qid(p, &fcall->qid); + break; + case TATTACH: + p = ixp_enc_u32(p, fcall->fid); + p = ixp_enc_u32(p, fcall->afid); + p = ixp_enc_string(p, fcall->uname); + p = ixp_enc_string(p, fcall->aname); + break; + case RERROR: + p = ixp_enc_string(p, fcall->errstr); + break; + case TFLUSH: + p = ixp_enc_u16(p, fcall->oldtag); + break; + case TWALK: + p = ixp_enc_u32(p, fcall->fid); + p = ixp_enc_u32(p, fcall->newfid); + p = ixp_enc_u16(p, fcall->nwname); + for(i = 0; i < fcall->nwname; i++) + p = ixp_enc_string(p, fcall->wname[i]); + break; + case RWALK: + p = ixp_enc_u16(p, fcall->nwqid); + for(i = 0; i < fcall->nwqid; i++) + p = ixp_enc_qid(p, &fcall->wqid[i]); + break; + case TOPEN: + p = ixp_enc_u32(p, fcall->fid); + p = ixp_enc_u8(p, fcall->mode); + break; + case ROPEN: + case RCREATE: + p = ixp_enc_qid(p, &fcall->qid); + p = ixp_enc_u32(p, fcall->iounit); + break; + case TCREATE: + p = ixp_enc_u32(p, fcall->fid); + p = ixp_enc_string(p, fcall->name); + p = ixp_enc_u32(p, fcall->perm); + p = ixp_enc_u8(p, fcall->mode); + break; + case TREAD: + p = ixp_enc_u32(p, fcall->fid); + p = ixp_enc_u64(p, fcall->offset); + p = ixp_enc_u32(p, fcall->count); + break; + case RREAD: + p = ixp_enc_u32(p, fcall->count); + p = ixp_enc_data(p, fcall->data, fcall->count); + break; + case TWRITE: + p = ixp_enc_u32(p, fcall->fid); + p = ixp_enc_u64(p, fcall->offset); + p = ixp_enc_u32(p, fcall->count); + p = ixp_enc_data(p, fcall->data, fcall->count); + break; + case RWRITE: + p = ixp_enc_u32(p, fcall->count); + break; + case TCLUNK: + case TREMOVE: + case TSTAT: + p = ixp_enc_u32(p, fcall->fid); + break; + case RSTAT: + p = ixp_enc_u16(p, ixp_sizeof_stat(&fcall->stat)); + p = ixp_enc_stat(p, &fcall->stat); + break; + case TWSTAT: + p = ixp_enc_u32(p, fcall->fid); + p = ixp_enc_u16(p, ixp_sizeof_stat(&fcall->stat)); + p = ixp_enc_stat(p, &fcall->stat); + break; + } -void *ropen_message(int fd, size_t * msg_len) -{ - char *msg; - ResHeader h; - *msg_len = sizeof(ResHeader); - msg = cext_emallocz(*msg_len); - h.res = ROPEN; - h.fd = fd; - memcpy(msg, &h, sizeof(ResHeader)); - return msg; + if(msg + msize == p) + return msize; + return 0; } -void *rread_message(void *content, size_t content_len, size_t * msg_len) +unsigned int +ixp_msg_to_fcall(void *msg, unsigned int msglen, Fcall * fcall) { - char *msg; - ResHeader h; - *msg_len = sizeof(ResHeader) + content_len; - msg = cext_emallocz(*msg_len); - h.res = RREAD; - h.buf_len = content_len; - memcpy(msg, &h, sizeof(ResHeader)); - memmove(msg + sizeof(ResHeader), content, content_len); - return msg; -} + unsigned int i, msize; + unsigned short len; + void *p = ixp_dec_prefix(msg, &msize, &fcall->id, &fcall->tag); -void *rwrite_message(size_t * msg_len) -{ - char *msg; - ResHeader h; - *msg_len = sizeof(ResHeader); - msg = cext_emallocz(*msg_len); - h.res = RWRITE; - memcpy(msg, &h, sizeof(ResHeader)); - return msg; -} + if(msize > msglen) /* bad message */ + return 0; -void *rclose_message(size_t * msg_len) -{ - char *msg; - ResHeader h; - *msg_len = sizeof(ResHeader); - msg = cext_emallocz(*msg_len); - h.res = RCLUNK; - memcpy(msg, &h, sizeof(ResHeader)); - return msg; -} + switch (fcall->id) { + case TVERSION: + case RVERSION: + p = ixp_dec_u32(p, &fcall->maxmsg); + p = ixp_dec_string(p, fcall->version, sizeof(fcall->version), &len); + break; + case TAUTH: + p = ixp_dec_u32(p, &fcall->afid); + p = ixp_dec_string(p, fcall->uname, sizeof(fcall->uname), &len); + p = ixp_dec_string(p, fcall->aname, sizeof(fcall->aname), &len); + break; + case RAUTH: + p = ixp_dec_qid(p, &fcall->aqid); + break; + case RATTACH: + p = ixp_dec_qid(p, &fcall->qid); + break; + case TATTACH: + p = ixp_dec_u32(p, &fcall->fid); + p = ixp_dec_u32(p, &fcall->afid); + p = ixp_dec_string(p, fcall->uname, sizeof(fcall->uname), &len); + p = ixp_dec_string(p, fcall->aname, sizeof(fcall->aname), &len); + break; + case RERROR: + p = ixp_dec_string(p, fcall->errstr, sizeof(fcall->errstr), &len); + break; + case TFLUSH: + p = ixp_dec_u16(p, &fcall->oldtag); + break; + case TWALK: + p = ixp_dec_u32(p, &fcall->fid); + p = ixp_dec_u32(p, &fcall->newfid); + p = ixp_dec_u16(p, &fcall->nwname); + for(i = 0; i < fcall->nwname; i++) { -void *rremove_message(size_t * msg_len) -{ - char *msg; - ResHeader h; - *msg_len = sizeof(ResHeader); - msg = cext_emallocz(*msg_len); - h.res = RREMOVE; - memcpy(msg, &h, sizeof(ResHeader)); - return msg; -} + p = ixp_dec_string(p, fcall->wname[i], IXP_MAX_FLEN, &len); + } + break; + case RWALK: + p = ixp_dec_u16(p, &fcall->nwqid); + for(i = 0; i < fcall->nwqid; i++) + p = ixp_dec_qid(p, &fcall->wqid[i]); + break; + case TOPEN: + p = ixp_dec_u32(p, &fcall->fid); + p = ixp_dec_u8(p, &fcall->mode); + break; + case ROPEN: + case RCREATE: + p = ixp_dec_qid(p, &fcall->qid); + p = ixp_dec_u32(p, &fcall->iounit); + break; + case TCREATE: + p = ixp_dec_u32(p, &fcall->fid); + p = ixp_dec_string(p, fcall->name, sizeof(fcall->name), &len); + p = ixp_dec_u32(p, &fcall->perm); + p = ixp_dec_u8(p, &fcall->mode); + break; + case TREAD: + p = ixp_dec_u32(p, &fcall->fid); + p = ixp_dec_u64(p, &fcall->offset); + p = ixp_dec_u32(p, &fcall->count); + break; + case RREAD: + p = ixp_dec_u32(p, &fcall->count); + p = ixp_dec_data(p, fcall->data, fcall->count); + break; + case TWRITE: + p = ixp_dec_u32(p, &fcall->fid); + p = ixp_dec_u64(p, &fcall->offset); + p = ixp_dec_u32(p, &fcall->count); + p = ixp_dec_data(p, fcall->data, fcall->count); + break; + case RWRITE: + p = ixp_dec_u32(p, &fcall->count); + break; + case TCLUNK: + case TREMOVE: + case TSTAT: + p = ixp_dec_u32(p, &fcall->fid); + break; + case RSTAT: + p = ixp_dec_u16(p, &len); + p = ixp_dec_stat(p, &fcall->stat); + break; + case TWSTAT: + p = ixp_dec_u32(p, &fcall->fid); + p = ixp_dec_u16(p, &len); + p = ixp_dec_stat(p, &fcall->stat); + break; + } -void *rerror_message(char *errstr, size_t * msg_len) -{ - char *msg; - size_t len = strlen(errstr) + 1; - ResHeader h; - *msg_len = sizeof(ResHeader) + len; - msg = cext_emallocz(*msg_len); - h.res = RERROR; - memcpy(msg, &h, sizeof(ResHeader)); - memmove(msg + sizeof(ResHeader), errstr, len); - return msg; + if(msg + msize == p) + return msize; + return 0; } diff --git a/libixp/ramfs.c b/libixp/ramfs.c @@ -1,297 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "ixp.h" - -#include <cext.h> - -int is_directory(File * f) -{ - return !f->size && f->content; -} - -File *ixp_create(IXPServer * s, char *path) -{ - File *f, *p; - char *buf = strdup(path); - char *tok, *tok_ptr; - - if (!path) - return 0; - - /* cannot create a directory with empty name */ - if (buf[strlen(buf) - 1] == '/') - return 0; - tok = strtok_r(buf, "/", &tok_ptr); - p = s->root; - f = p->content; - /* first determine the path as it exists already */ - while (f && tok) { - if (!strcmp(f->name, tok)) { - tok = strtok_r(0, "/", &tok_ptr); - p = f; - if (tok && is_directory(f)) - f = f->content; - else - break; - continue; - } - f = f->next; - } - if (p->size && tok) { - free(buf); - return 0; /* cannot create subdirectory, if file has - * content */ - } - /* only create missing parts, if file is directory */ - while (tok) { - f = (File *) cext_emallocz(sizeof(File)); - f->name = strdup(tok); - f->parent = p; - if (p->content) { - p = p->content; - while (p->next) { - p = p->next; - } - p->next = f; - } else { - p->content = f; - } - p = f; - tok = strtok_r(0, "/", &tok_ptr); - } - free(buf); - return f; -} - -static int comp_file_name(const void *f1, const void *f2) -{ - File *f = (File *) f1; - File *p = (File *) f2; - return strcmp(*(char **) f->name, *(char **) p->name); -} - -static char *xls(File * f) -{ - File *p; - char *result = 0; - size_t size = 1; /* for \n */ - int num = 0, i; - File **tmp; - - for (p = f; p; p = p->next) - num++; - tmp = cext_emallocz(sizeof(File *) * num); - i = 0; - for (p = f; p; p = p->next) { - size += strlen(p->name) + 1; - if (is_directory(p)) - size++; - tmp[i++] = p; - } - qsort(tmp, num, sizeof(File *), comp_file_name); - result = cext_emallocz(size); - for (i = 0; i < num; i++) { - strncat(result, tmp[i]->name, size); - if (is_directory(tmp[i])) - strncat(result, "/\n", size); - else - strncat(result, "\n", size); - } - free(tmp); - return result; -} - -File *ixp_open(IXPServer * s, char *path) -{ - File *f; - - f = ixp_walk(s, path); - if (!f) { - set_error(s, "file does not exist"); - return nil; - } - return f; -} - -void ixp_close(IXPServer * s, int fd) -{ - File *f = fd_to_file(s, fd); - if (!f) - set_error(s, "invalid file descriptor"); -} - -size_t -ixp_read(IXPServer * s, int fd, size_t offset, void *out_buf, - size_t out_buf_len) -{ - File *f = fd_to_file(s, fd); - void *result = 0; - size_t len = 0, res_len = 0; - - if (!f) { - set_error(s, "invalid file descriptor"); - return 0; - } - /* callback */ - if (f->before_read) - f->before_read(s, f); - if (is_directory(f)) { - result = xls(f->content); - res_len = strlen(result); - } else if (f->size) { - result = f->content; - res_len = f->size; - } - if (offset > res_len) { - set_error(s, "invalid offset when reading file"); - if (is_directory(f)) - free(result); - return 0; - } - if (result) { - len = res_len - offset; - if (len > out_buf_len) - len = out_buf_len; - memcpy(out_buf, (char *) result + offset, len); - if (is_directory(f)) - free(result); - } - return len; -} - -void -ixp_write(IXPServer * s, int fd, size_t offset, void *content, - size_t in_len) -{ - File *f = fd_to_file(s, fd); - - if (!f) { - set_error(s, "invalid file descriptor"); - return; - } - if (is_directory(f)) { - /* we cannot write to directories */ - set_error(s, "cannot write to a directory"); - return; - } - if (in_len) { - /* offset 0 flushes the file */ - if (!offset || (offset + in_len > f->size)) { - f->content = realloc(f->content, offset + in_len + 1); - f->size = offset + in_len; - } - memcpy((char *) f->content + offset, content, in_len); - /* internal EOF character */ - ((char *) f->content)[f->size] = 0; - } else if (!offset) { - /* blank file */ - if (f->content) - free(f->content); - f->content = 0; - f->size = 0; - } - /* callback */ - if (f->after_write) - f->after_write(s, f); -} - -static void xremove(IXPServer * s, File * f) -{ - if (!f) - return; - if (f->next) { - xremove(s, f->next); - if (s->errstr) - return; - } - if (!f->bind && is_directory(f)) { - xremove(s, f->content); - if (s->errstr) - return; - } - if (f->content && f->size) { - free(f->content); - } - if (f != s->root) { - if (f->name) { - free(f->name); - } - free(f); - } -} - -void ixp_remove_file(IXPServer * s, File * f) -{ - File *p, *n; - set_error(s, 0); - if (!f) { - set_error(s, "file does not exist"); - return; - } - /* detach */ - p = f->parent; - n = f->next; - f->next = 0; - if (p) { - if (p->content == f) - p->content = n; - else { - p = p->content; - while (p && (p->next != f)) - p = p->next; - if (p) - p->next = n; - } - } - /* remove now */ - xremove(s, f); -} - - -void ixp_remove(IXPServer * s, char *path) -{ - ixp_remove_file(s, ixp_walk(s, path)); -} - -File *ixp_walk(IXPServer * s, char *path) -{ - File *f = 0; - File *n; - char *buf; - char *tok, *tok_ptr; - - if (!path) { - return 0; - } - buf = strdup(path); - - tok = strtok_r(buf, "/", &tok_ptr); - f = s->root->content; - if (!tok && buf[0] == '/') { - f = s->root; - } - while (f && tok) { - n = f->next; - if (!strcmp(f->name, tok)) { - tok = strtok_r(0, "/", &tok_ptr); - if (tok && f->size) - return 0; - if (!tok) - break; - f = f->content; - continue; - } - f = n; - } - if (f && (path[strlen(path) - 1] == '/') && !is_directory(f)) - f = 0; - free(buf); - return f; -} diff --git a/libixp/server.c b/libixp/server.c @@ -5,434 +5,69 @@ #include <errno.h> #include <fcntl.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> -#include <signal.h> #include <string.h> -#include <sys/un.h> #include <sys/stat.h> #include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> #include "ixp.h" +#include "cext.h" -#include <cext.h> - -static Connection zero_conn = { 0 }; -static int user_fd = -1; - -void set_error(IXPServer * s, char *errstr) -{ - if (s->errstr) - free(s->errstr); - if (errstr) - s->errstr = strdup(errstr); - else - s->errstr = 0; -} - -File *fd_to_file(IXPServer * s, int fd) -{ - int cidx = fd / MAX_CONN; - int fidx = fd - (cidx * MAX_CONN); - - return s->conn[cidx].files[fidx]; -} - -static void handle_ixp_create(Connection * c) -{ - c->s->create(c->s, ((char *) c->data) + sizeof(ReqHeader)); - free(c->data); - c->data = c->s->errstr ? - rerror_message(c->s->errstr, &c->len) : rcreate_message(&c->len); - c->remain = c->len; -} - -static void handle_ixp_open(Connection * c) -{ - int i; - - /* seek next free slot */ - for (i = 0; (i < MAX_OPEN_FILES) && c->files[i]; i++); - if (i == MAX_OPEN_FILES) { - fprintf(stderr, "%s", - "ixp: server: maximum of open files, try again later.\n"); - free(c->data); - c->data = - rerror_message("maximum open files reached, close files first", - &c->len); - c->remain = c->len; - return; - } - c->files[i] = c->s->open(c->s, ((char *) c->data) + sizeof(ReqHeader)); - c->seen[i] = MAX_SEEN_SHUTDOWN; - free(c->data); - c->data = c->s->errstr ? - rerror_message(c->s->errstr, - &c->len) : ropen_message(i + MAX_CONN * c->index, - &c->len); - c->remain = c->len; -} - -static void handle_ixp_read(Connection * c, ReqHeader * h) -{ - void *data = 0; - size_t out_len; - - data = cext_emallocz(h->buf_len); - out_len = c->s->read(c->s, h->fd, h->offset, data, h->buf_len); - free(c->data); - if (c->s->errstr) - c->data = rerror_message(c->s->errstr, &c->len); - else - c->data = rread_message(data, out_len, &c->len); - c->remain = c->len; - free(data); -} - -static void handle_ixp_write(Connection * c, ReqHeader * h) -{ - c->s->write(c->s, h->fd, h->offset, - ((char *) c->data) + sizeof(ReqHeader), h->buf_len); - free(c->data); - if (c->s->errstr) - c->data = rerror_message(c->s->errstr, &c->len); - else - c->data = rwrite_message(&c->len); - c->remain = c->len; -} - -static void handle_ixp_close(Connection * c, ReqHeader * h) -{ - int fidx = h->fd - (c->index * MAX_CONN); - - c->s->close(c->s, h->fd); - c->files[fidx] = 0; - free(c->data); - if (c->s->errstr) - c->data = rerror_message(c->s->errstr, &c->len); - else - c->data = rclose_message(&c->len); - c->remain = c->len; -} - -static void handle_ixp_remove(Connection * c) -{ - c->s->remove(c->s, ((char *) c->data) + sizeof(ReqHeader)); - free(c->data); - c->data = c->s->errstr ? - rerror_message(c->s->errstr, &c->len) : rremove_message(&c->len); - c->remain = c->len; -} - -static void check_ixp_request(Connection * c) -{ - ReqHeader h; - /* check pending request */ - if (c->s->errstr) - set_error(c->s, 0); - memcpy(&h, c->data, sizeof(ReqHeader)); - switch (h.req) { - case TCREATE: - handle_ixp_create(c); - break; - case TREMOVE: - handle_ixp_remove(c); - break; - case TOPEN: - handle_ixp_open(c); - break; - case TCLUNK: - handle_ixp_close(c, &h); - break; - case TREAD: - handle_ixp_read(c, &h); - break; - case TWRITE: - handle_ixp_write(c, &h); - break; - default: - fprintf(stderr, "%s", "ixp: server: invalid request\n"); - free(c->data); - c->len = c->remain = 0; - break; - } -} - -static void update_conns(IXPServer * s) -{ - int i; - - FD_ZERO(&s->rd); - FD_ZERO(&s->wr); - for (i = 0; i < MAX_CONN; i++) { - if (s->conn[i].fd >= 0) { - s->nfds = xMAX(s->nfds, s->conn[i].fd); - if (s->conn[i].read && !s->conn[i].mode - && (!s->conn[i].len || s->conn[i].remain)) { - FD_SET(s->conn[i].fd, &s->rd); - } - if (s->conn[i].write && s->conn[i].mode && s->conn[i].remain) { - FD_SET(s->conn[i].fd, &s->wr); - } - } - } -} - -static void close_conn(Connection * c) -{ - int i; - /* shutdown connection and cleanup open files */ - shutdown(c->fd, SHUT_RDWR); - close(c->fd); - c->fd = -1; - c->mode = 0; - for (i = 0; i < MAX_OPEN_FILES; i++) { - if (c->files[i]) - c->files[i] = 0; - } -} - -static void read_conn(Connection * c) -{ - size_t r; - - if (!c->header) { - r = read(c->fd, &c->len, sizeof(size_t)); - if (r != sizeof(size_t)) { - close_conn(c); - return; - } - c->remain = c->len; - c->data = cext_emallocz(c->len); - c->header = 1; - } - r = read(c->fd, ((char *) c->data) + c->len - c->remain, c->remain); - if (r < 1) { - close_conn(c); - return; - } - c->remain -= r; - - if (c->remain == 0) { - /* check IXP request */ - c->mode = 1; /* next mode is response */ - check_ixp_request(c); - c->header = 0; - } -} - -static void write_conn(Connection * c) -{ - size_t r; - - if (!c->header) { - r = write(c->fd, &c->len, sizeof(size_t)); - if (r != sizeof(size_t)) { - close_conn(c); - } - c->header = 1; - } - r = write(c->fd, ((char *) c->data) + c->len - c->remain, c->remain); - if (r < 1) { - close_conn(c); - return; - } - c->remain -= r; - - if (c->remain == 0) { - c->len = 0; - c->mode = 0; - c->header = 0; - } -} - -static void new_conn(Connection * c) +static void +prepare_select(IXPServer *s) { - int r, i; - socklen_t l; - struct sockaddr_un name = { 0 }; - - l = sizeof(name); - if ((r = accept(c->fd, (struct sockaddr *) &name, &l)) < 0) { - perror("ixp: server: cannot accept connection"); - return; - } - if (c->s->runlevel == SHUTDOWN) { - fprintf(stderr, "%s", - "ixp: server: connection refused, server is shutting down.\n"); - close(r); - return; - } - for (i = 0; i < MAX_CONN; i++) { - if (c->s->conn[i].fd == -1) { /* free connection */ - c->s->conn[i] = zero_conn; - c->s->conn[i].s = c->s; - c->s->conn[i].index = i; - c->s->conn[i].fd = r; - c->s->conn[i].read = read_conn; - c->s->conn[i].write = write_conn; - break; - } - } - - if (i == MAX_CONN) { - fprintf(stderr, "%s", - "ixp: server: connection refused, try again later.\n"); - close(r); - } -} - - -static int check_open_files(Connection * c) -{ - int i; - for (i = 0; i < MAX_OPEN_FILES; i++) { - if (c->files[i] && c->seen[i]) { - c->seen[i]--; - return 1; - } - } - return 0; -} - -static void handle_socks(IXPServer * s) -{ - int i, now = 1; - for (i = 0; i < MAX_CONN; i++) { - if (s->conn[i].fd >= 0) { - if (FD_ISSET(s->conn[i].fd, &s->rd) && s->conn[i].read) { - /* call back read handler */ - s->conn[i].read(&s->conn[i]); - } else if (FD_ISSET(s->conn[i].fd, &s->wr) && s->conn[i].write) { - /* call back write handler */ - s->conn[i].write(&s->conn[i]); - } - /* - * don't shutdown, if there're remaining bits or if - * still responses are sent or still opened files - */ - if ((s->runlevel == SHUTDOWN) - && (check_open_files(&s->conn[i]) - || (s->conn[i].remain > 0) - || s->conn[i].mode)) - now = 0; - } - } - if ((s->runlevel == SHUTDOWN) && now) - s->runlevel = HALT; /* real stop */ -} - -IXPServer *init_server(char *sockfile, void (*cleanup) (void)) -{ - int i; - struct sockaddr_un addr = { 0 }; - int yes = 1; - socklen_t su_len; - IXPServer *s; - - /* init */ - s = (IXPServer *) cext_emallocz(sizeof(IXPServer)); - s->sockfile = sockfile; - s->root = (File *) cext_emallocz(sizeof(File)); - s->runlevel = HALT; /* initially server is not running */ - s->create = ixp_create; - s->remove = ixp_remove; - s->open = ixp_open; - s->close = ixp_close; - s->read = ixp_read; - s->write = ixp_write; - s->root->name = strdup(""); - for (i = 0; i < MAX_CONN; i++) { - s->conn[i].s = s; - s->conn[i].fd = -1; - s->conn[i].index = i; - } - - signal(SIGPIPE, SIG_IGN); - if ((s->conn[0].fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - perror("ixp: server: socket"); - free(s); - return 0; - } - if (setsockopt(s->conn[0].fd, SOL_SOCKET, SO_REUSEADDR, - (char *) &yes, sizeof(yes)) < 0) { - perror("ixp: server: setsockopt"); - close(s->conn[0].fd); - free(s); - return 0; - } - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, sockfile, sizeof(addr.sun_path)); - su_len = sizeof(struct sockaddr) + strlen(addr.sun_path); - - if (bind(s->conn[0].fd, (struct sockaddr *) &addr, su_len) < 0) { - perror("ixp: server: cannot bind socket"); - close(s->conn[0].fd); - free(s); - return 0; - } - chmod(sockfile, S_IRWXU); - - if (listen(s->conn[0].fd, MAX_CONN) < 0) { - perror("ixp: server: cannot listen on socket"); - close(s->conn[0].fd); - free(s); - return 0; - } - s->conn[0].read = new_conn; - - /* register to cleanup function, to unlink sockfile */ - if (cleanup) - atexit(cleanup); - - return s; + int i; + FD_ZERO(&s->rd); + for(i = 0; (i < s->connsz) && s->conn[i]; i++) { + if(s->maxfd < s->conn[i]->fd) + s->maxfd = s->conn[i]->fd; + if(s->conn[i]->read) + FD_SET(s->conn[i]->fd, &s->rd); + } } -void -run_server_with_fd_support(IXPServer * s, int fd, - void (*fd_read) (Connection *), - void (*fd_write) (Connection *)) +static void +handle_conns(IXPServer *s) { - s->conn[1] = zero_conn; - s->conn[1].index = 1; - s->conn[1].s = s; - s->conn[1].fd = user_fd = fd; - s->conn[1].read = fd_read; - s->conn[1].write = fd_write; - run_server(s); + int i; + for(i = 0; (i < s->connsz) && s->conn[i]; i++) + if(FD_ISSET(s->conn[i]->fd, &s->rd) && s->conn[i]->read) + /* call read handler */ + s->conn[i]->read(s, s->conn[i]); } -void run_server(IXPServer * s) +char * +ixp_server_loop(IXPServer *s) { - int r, i; - s->runlevel = RUNNING; + int r; + s->running = 1; - /* main loop */ - while (s->runlevel != HALT) { + /* main loop */ + while(s->running && s->conn) { - update_conns(s); + prepare_select(s); - r = select(s->nfds + 1, &s->rd, &s->wr, 0, 0); - if (r == -1 && errno == EINTR) - continue; - if (r < 0) { - perror("ixp: server: select"); - break; /* allow cleanups in IXP using app */ - } else if (r > 0) { - handle_socks(s); - } - } - /* shut down server */ - for (i = MAX_CONN - 1; i >= 0; i--) { - if (s->conn[i].fd >= 0 && s->conn[i].fd != user_fd) { - close(s->conn[i].fd); - } - } + r = select(s->maxfd + 1, &s->rd, 0, 0, 0); + if(r == -1 && errno == EINTR) + continue; + if(r < 0) + return "fatal select error"; + else if(r > 0) + handle_conns(s); + } + return nil; } -void deinit_server(IXPServer * s) +IXPMap * +ixp_server_fid2map(IXPConn *c, unsigned int fid) { - unlink(s->sockfile); - ixp_remove(s, "/"); - free(s); + size_t i; + for(i = 0; (i < c->mapsz) && c->map[i]; i++) + if(c->map[i]->fid == fid) + return c->map[i]; + return nil; } diff --git a/libixp/socket.c b/libixp/socket.c @@ -0,0 +1,204 @@ +/* + * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> + * See LICENSE file for license details. + */ + +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <netdb.h> +#include <sys/un.h> +#include <unistd.h> + +#include "cext.h" +#include "ixp.h" + +static int +connect_unix_sock(char *address) +{ + int fd = 0; + struct sockaddr_un addr = { 0 }; + socklen_t su_len; + + /* init */ + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, address, sizeof(addr.sun_path)); + su_len = sizeof(struct sockaddr) + strlen(addr.sun_path); + + if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return -1; + if(connect(fd, (struct sockaddr *) &addr, su_len)) { + close(fd); + return -1; + } + return fd; +} + +static int +connect_inet_sock(char *host) +{ + int fd = 0; + struct sockaddr_in addr = { 0 }; + struct hostent *hp; + char *port = strrchr(host, '!'); + const char *errstr = nil; + unsigned int prt; + + *port = 0; + port++; + prt = cext_strtonum(port, 1024, 65535, &errstr); + if(errstr) + return -1; + + /* init */ + if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return -1; + hp = gethostbyname(host); + addr.sin_family = AF_INET; + addr.sin_port = htons(prt); + bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); + + if(connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))) { + close(fd); + return -1; + } + return fd; +} + +int +ixp_connect_sock(char *address) +{ + char *p = strchr(address, '!'); + char *addr, *type; + + if(!p) + return -1; + *p = 0; + + addr = &p[1]; + type = address; /* unix, inet */ + + if(!strncmp(type, "unix", 5)) + return connect_unix_sock(addr); + else if(!strncmp(type, "tcp", 4)) + return connect_inet_sock(addr); + return -1; +} + +int +ixp_accept_sock(int fd) +{ + socklen_t su_len; + struct sockaddr_un addr = { 0 }; + + su_len = sizeof(struct sockaddr); + return accept(fd, (struct sockaddr *) &addr, &su_len); +} + +static int +create_inet_sock(char *host, char **errstr) +{ + int fd; + struct sockaddr_in addr = { 0 }; + char *port = strrchr(host, '!'); + unsigned int prt; + + if(!port) { + *errstr = "no port provided in address"; + return -1; + } + *port = 0; + port++; + prt = cext_strtonum(port, 1024, 65535, (const char **)errstr); + if(*errstr) + return -1; + signal(SIGPIPE, SIG_IGN); + if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + *errstr = "cannot open socket"; + return -1; + } + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin_port = htons(prt); + + if(bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0) { + *errstr = "cannot bind socket"; + close(fd); + return -1; + } + + if(listen(fd, IXP_MAX_CACHE) < 0) { + *errstr = "cannot listen on socket"; + close(fd); + return -1; + } + return fd; +} + +static int +create_unix_sock(char *file, char **errstr) +{ + int fd; + int yes = 1; + struct sockaddr_un addr = { 0 }; + socklen_t su_len; + + signal(SIGPIPE, SIG_IGN); + if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { + *errstr = "cannot open socket"; + return -1; + } + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + (char *) &yes, sizeof(yes)) < 0) { + *errstr = "cannot set socket options"; + close(fd); + return -1; + } + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, file, sizeof(addr.sun_path)); + su_len = sizeof(struct sockaddr) + strlen(addr.sun_path); + + unlink(file); /* remove old socket, if any */ + if(bind(fd, (struct sockaddr *) &addr, su_len) < 0) { + *errstr = "cannot bind socket"; + close(fd); + return -1; + } + chmod(file, S_IRWXU); + + if(listen(fd, IXP_MAX_CACHE) < 0) { + *errstr = "cannot listen on socket"; + close(fd); + return -1; + } + return fd; +} + +int +ixp_create_sock(char *address, char **errstr) +{ + char *p = strchr(address, '!'); + char *addr, *type; + + if(!p) { + *errstr = "no socket type defined"; + return -1; + } + *p = 0; + + addr = &p[1]; + type = address; /* unix, inet */ + + if(!strncmp(type, "unix", 5)) + return create_unix_sock(addr, errstr); + else if(!strncmp(type, "tcp", 4)) + return create_inet_sock(addr, errstr); + else + *errstr = "unkown socket type"; + return -1; +} diff --git a/libixp/transport.c b/libixp/transport.c @@ -0,0 +1,81 @@ +/* + * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> + * See LICENSE file for license details. + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <unistd.h> + +#include "ixp.h" + +#include <cext.h> + +unsigned int +ixp_send_message(int fd, void *msg, unsigned int msize, char **errstr) +{ + unsigned int num = 0; + int r; + + /* send message */ + while(num < msize) { + r = write(fd, msg + num, msize - num); + if(r == -1 && errno == EINTR) + continue; + if(r < 1) { + *errstr = "cannot send message"; + return 0; + } + num += r; + } + return num; +} + +static unsigned int +ixp_recv_data(int fd, void *msg, unsigned int msize, char **errstr) +{ + unsigned int num = 0; + int r = 0; + + /* receive data */ + while(num < msize) { + r = read(fd, msg + num, msize - num); + if(r == -1 && errno == EINTR) + continue; + if(r < 1) { + *errstr = "cannot receive data"; + return 0; + } + num += r; + } + return num; +} + +unsigned int +ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr) +{ + unsigned int msize; + + /* receive header */ + if(ixp_recv_data(fd, msg, sizeof(unsigned int), errstr) != + sizeof(unsigned int)) + return 0; + ixp_dec_u32(msg, &msize); + if(msize > msglen) { + *errstr = "message size exceeds buffer size"; + return 0; + } + /* receive message */ + if(ixp_recv_data + (fd, msg + sizeof(unsigned int), msize - sizeof(unsigned int), + errstr) + != msize - sizeof(unsigned int)) + return 0; + return msize; +} diff --git a/libixp2/Makefile b/libixp2/Makefile @@ -1,25 +0,0 @@ -# libixp - lib ixp protocol -# (C)opyright MMIV-MMVI Anselm R. Garbe - -include ../config.mk - -CFLAGS += -I ../libcext - -SRC = client.c convert.c message.c server.c socket.c transport.c - -OBJ = ${SRC:.c=.o} - -all: libixp - @echo built libixp2 - -.c.o: - @echo CC $< - @${CC} -c ${CFLAGS} $< - -libixp: ${OBJ} - @echo AR $@.a - @${AR} $@.a ${OBJ} - @${RANLIB} $@.a - -clean: - rm -f libixp.a *.o diff --git a/libixp2/client.c b/libixp2/client.c @@ -1,194 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <unistd.h> - -#include "cext.h" -#include "ixp.h" - -static unsigned char msg[IXP_MAX_MSG]; - -static int -do_fcall(IXPClient * c) -{ - unsigned int msize = ixp_fcall_to_msg(&c->fcall, msg, IXP_MAX_MSG); - c->errstr = 0; - if(ixp_send_message(c->fd, msg, msize, &c->errstr) != msize) - return -1; - if(!ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &c->errstr)) - return -1; - if(!(msize = ixp_msg_to_fcall(msg, IXP_MAX_MSG, &c->fcall))) { - c->errstr = "received bad message"; - return -1; - } - if(c->fcall.id == RERROR) { - c->errstr = c->fcall.errstr; - return -1; - } - return 0; -} - -int -ixp_client_init(IXPClient * c, char *sockfile) -{ - if((c->fd = ixp_connect_sock(sockfile)) < 0) { - c->errstr = "cannot connect server"; - return -1; - } - /* version */ - c->fcall.id = TVERSION; - c->fcall.tag = IXP_NOTAG; - c->fcall.maxmsg = IXP_MAX_MSG; - cext_strlcpy(c->fcall.version, IXP_VERSION, sizeof(c->fcall.version)); - if(do_fcall(c) == -1) { - ixp_client_deinit(c); - return -1; - } - if(strncmp(c->fcall.version, IXP_VERSION, strlen(IXP_VERSION))) { - c->errstr = "9P versions differ"; - ixp_client_deinit(c); - return -1; /* we cannot handle this version */ - } - c->root_fid = getpid(); - - /* attach */ - c->fcall.id = TATTACH; - c->fcall.tag = IXP_NOTAG; - c->fcall.fid = c->root_fid; - c->fcall.afid = IXP_NOFID; - cext_strlcpy(c->fcall.uname, getenv("USER"), sizeof(c->fcall.uname)); - c->fcall.aname[0] = 0; - if(do_fcall(c) == -1) { - ixp_client_deinit(c); - return -1; - } - c->root_qid = c->fcall.qid; - return 0; -} - -int -ixp_client_remove(IXPClient * c, unsigned int newfid, char *filepath) -{ - if(ixp_client_walk(c, newfid, filepath) == -1) - return -1; - /* remove */ - c->fcall.id = TREMOVE; - c->fcall.tag = IXP_NOTAG; - c->fcall.fid = newfid; - return do_fcall(c); -} - -int -ixp_client_create(IXPClient * c, unsigned int dirfid, char *name, - unsigned int perm, unsigned char mode) -{ - /* create */ - c->fcall.id = TCREATE; - c->fcall.tag = IXP_NOTAG; - c->fcall.fid = dirfid; - cext_strlcpy(c->fcall.name, name, sizeof(c->fcall.name)); - c->fcall.perm = perm; - c->fcall.mode = mode; - return do_fcall(c); -} - -int -ixp_client_walk(IXPClient * c, unsigned int newfid, char *filepath) -{ - unsigned int i; - char *wname[IXP_MAX_WELEM]; - /* walk */ - c->fcall.id = TWALK; - c->fcall.fid = c->root_fid; - c->fcall.newfid = newfid; - if(filepath) { - cext_strlcpy(c->fcall.name, filepath, sizeof(c->fcall.name)); - c->fcall.nwname = - cext_tokenize(wname, IXP_MAX_WELEM, c->fcall.name, '/'); - for(i = 0; i < c->fcall.nwname; i++) - cext_strlcpy(c->fcall.wname[i], wname[i], sizeof(c->fcall.wname[i])); - } - return do_fcall(c); -} - -int -ixp_client_open(IXPClient * c, unsigned int newfid, char *filepath, - unsigned char mode) -{ - if(ixp_client_walk(c, newfid, filepath) == -1) - return -1; - - /* open */ - c->fcall.id = TOPEN; - c->fcall.tag = IXP_NOTAG; - c->fcall.fid = newfid; - c->fcall.mode = mode; - return do_fcall(c); -} - -int -ixp_client_read(IXPClient * c, unsigned int fid, unsigned long long offset, - void *result, unsigned int res_len) -{ - unsigned int bytes = c->fcall.iounit; - - /* read */ - c->fcall.id = TREAD; - c->fcall.tag = IXP_NOTAG; - c->fcall.fid = fid; - c->fcall.offset = offset; - c->fcall.count = res_len < bytes ? res_len : bytes; - if(do_fcall(c) == -1) - return -1; - memcpy(result, c->fcall.data, c->fcall.count); - return c->fcall.count; -} - -int -ixp_client_write(IXPClient * c, unsigned int fid, - unsigned long long offset, unsigned int count, - unsigned char *data) -{ - if(count > c->fcall.iounit) - { - c->errstr = "iounit exceeded"; - return -1; - } - /* write */ - c->fcall.id = TWRITE; - c->fcall.tag = IXP_NOTAG; - c->fcall.fid = fid; - c->fcall.offset = offset; - c->fcall.count = count; - memcpy(c->fcall.data, data, count); - if(do_fcall(c) == -1) - return -1; - return c->fcall.count; -} - -int -ixp_client_close(IXPClient * c, unsigned int fid) -{ - /* clunk */ - c->fcall.id = TCLUNK; - c->fcall.tag = IXP_NOTAG; - c->fcall.fid = fid; - return do_fcall(c); -} - -void -ixp_client_deinit(IXPClient * c) -{ - /* session finished, now shutdown */ - if(c->fd) { - shutdown(c->fd, SHUT_RDWR); - close(c->fd); - } -} diff --git a/libixp2/convert.c b/libixp2/convert.c @@ -1,197 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <stdlib.h> -#include <string.h> -#include "ixp.h" - -/* encode/decode stuff */ - -void * -ixp_enc_u8(unsigned char *msg, unsigned char val) -{ - msg[0] = val; - return &msg[1]; -} - -void * -ixp_dec_u8(unsigned char *msg, unsigned char *val) -{ - *val = msg[0]; - return &msg[1]; -} - -void * -ixp_enc_u16(unsigned char *msg, unsigned short val) -{ - msg[0] = val; - msg[1] = val >> 8; - return &msg[2]; -} - -void * -ixp_dec_u16(unsigned char *msg, unsigned short *val) -{ - *val = msg[0] | (msg[1] << 8); - return &msg[2]; -} - -void * -ixp_enc_u32(unsigned char *msg, unsigned int val) -{ - msg[0] = val; - msg[1] = val >> 8; - msg[2] = val >> 16; - msg[3] = val >> 24; - return &msg[4]; -} - -void * -ixp_dec_u32(unsigned char *msg, unsigned int *val) -{ - *val = msg[0] | (msg[1] << 8) | (msg[2] << 16) | (msg[3] << 24); - return &msg[4]; -} - -void * -ixp_enc_u64(unsigned char *msg, unsigned long long val) -{ - msg[0] = val; - msg[1] = val >> 8; - msg[2] = val >> 16; - msg[3] = val >> 24; - msg[4] = val >> 32; - msg[5] = val >> 40; - msg[6] = val >> 48; - msg[7] = val >> 56; - return &msg[8]; -} - -void * -ixp_dec_u64(unsigned char *msg, unsigned long long *val) -{ - *val = - (unsigned long long) msg[0] | ((unsigned long long) msg[1] << 8) | - ((unsigned long long) msg[2] << 16) | ((unsigned long long) msg[3] - << 24) | ((unsigned long - long) msg[4] << - 32) | ((unsigned - long long) - msg[5] << - 40) | - ((unsigned long long) msg[6] << 48) | ((unsigned long long) msg[7] - << 56); - return &msg[8]; -} - -void * -ixp_enc_string(unsigned char *msg, const char *s) -{ - unsigned short len = s ? strlen(s) : 0; - msg = ixp_enc_u16(msg, len); - if(s) - memcpy(msg, s, len); - return &msg[len]; -} - -void * -ixp_dec_string(unsigned char *msg, char *string, unsigned short stringlen, - unsigned short *len) -{ - msg = ixp_dec_u16(msg, len); - if(!(*len)) - return msg; - if(*len > stringlen - 1) - /* might never happen if stringlen == IXP_MAX_MSG */ - string[0] = 0; - else { - memcpy(string, msg, *len); - string[*len] = 0; - } - return &msg[*len]; -} - -void * -ixp_enc_data(unsigned char *msg, unsigned char *data, unsigned int datalen) -{ - memcpy(msg, data, datalen); - return &msg[datalen]; -} - -void * -ixp_dec_data(unsigned char *msg, unsigned char *data, unsigned int datalen) -{ - memcpy(data, msg, datalen); - return &msg[datalen]; -} - -void * -ixp_enc_prefix(unsigned char *msg, unsigned int size, unsigned char id, - unsigned short tag) -{ - msg = ixp_enc_u32(msg, size); - msg = ixp_enc_u8(msg, id); - return ixp_enc_u16(msg, tag); -} - -void * -ixp_dec_prefix(unsigned char *msg, unsigned int *size, unsigned char *id, - unsigned short *tag) -{ - msg = ixp_dec_u32(msg, size); - msg = ixp_dec_u8(msg, id); - return ixp_dec_u16(msg, tag); -} - -void * -ixp_enc_qid(unsigned char *msg, Qid * qid) -{ - msg = ixp_enc_u8(msg, qid->type); - msg = ixp_enc_u32(msg, qid->version); - return ixp_enc_u64(msg, qid->path); -} - -void * -ixp_dec_qid(unsigned char *msg, Qid * qid) -{ - msg = ixp_dec_u8(msg, &qid->type); - msg = ixp_dec_u32(msg, &qid->version); - return ixp_dec_u64(msg, &qid->path); -} - -void * -ixp_enc_stat(unsigned char *msg, Stat * stat) -{ - msg = ixp_enc_u16(msg, ixp_sizeof_stat(stat) - sizeof(unsigned short)); - msg = ixp_enc_u16(msg, stat->type); - msg = ixp_enc_u32(msg, stat->dev); - msg = ixp_enc_qid(msg, &stat->qid); - msg = ixp_enc_u32(msg, stat->mode); - msg = ixp_enc_u32(msg, stat->atime); - msg = ixp_enc_u32(msg, stat->mtime); - msg = ixp_enc_u64(msg, stat->length); - msg = ixp_enc_string(msg, stat->name); - msg = ixp_enc_string(msg, stat->uid); - msg = ixp_enc_string(msg, stat->gid); - return ixp_enc_string(msg, stat->muid); -} - -void * -ixp_dec_stat(unsigned char *msg, Stat * stat) -{ - unsigned short dummy; - msg += sizeof(unsigned short); - msg = ixp_dec_u16(msg, &stat->type); - msg = ixp_dec_u32(msg, &stat->dev); - msg = ixp_dec_qid(msg, &stat->qid); - msg = ixp_dec_u32(msg, &stat->mode); - msg = ixp_dec_u32(msg, &stat->atime); - msg = ixp_dec_u32(msg, &stat->mtime); - msg = ixp_dec_u64(msg, &stat->length); - msg = ixp_dec_string(msg, stat->name, sizeof(stat->name), &dummy); - msg = ixp_dec_string(msg, stat->uid, sizeof(stat->uid), &dummy); - msg = ixp_dec_string(msg, stat->gid, sizeof(stat->gid), &dummy); - return ixp_dec_string(msg, stat->muid, sizeof(stat->muid), &dummy); -} diff --git a/libixp2/ixp.h b/libixp2/ixp.h @@ -1,289 +0,0 @@ -/* - *(C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - *See LICENSE file for license details. - */ - -#include <sys/types.h> - -#ifndef nil -#define nil 0 -#endif - -#define IXP_VERSION "9P2000" -#define IXP_MAX_VERSION 32 -#define IXP_MAX_ERROR 128 -#define IXP_MAX_CACHE 32 -#define IXP_MAX_MSG 8192 -#define IXP_MAX_FLEN 128 -#define IXP_MAX_ULEN 32 -#define IXP_MAX_STAT 64 -#define IXP_MAX_WELEM 16 /*MAXWELEM */ -#define IXP_MAX_TFUNCS 14 - - -/* - size[4] Tversion tag[2] msize[4] version[s] - size[4] Rversion tag[2] msize[4] version[s] - size[4] Tauth tag[2] afid[4] uname[s] aname[s] - size[4] Rauth tag[2] aqid[13] - size[4] Rerror tag[2] ename[s] - size[4] Tflush tag[2] oldtag[2] - size[4] Rflush tag[2] - size[4] Tattach tag[2] fid[4] afid[4] uname[s] aname[s] - size[4] Rattach tag[2] qid[13] - size[4] Twalk tag[2] fid[4] newfid[4] nwname[2] nwname*(wname[s]) - size[4] Rwalk tag[2] nwqid[2] nwqid*(wqid[13]) - size[4] Topen tag[2] fid[4] mode[1] - size[4] Ropen tag[2] qid[13] iounit[4] - size[4] Tcreate tag[2] fid[4] name[s] perm[4] mode[1] - size[4] Rcreate tag[2] qid[13] iounit[4] - size[4] Tread tag[2] fid[4] offset[8] count[4] - size[4] Rread tag[2] count[4] data[count] - size[4] Twrite tag[2] fid[4] offset[8] count[4] data[count] - size[4] Rwrite tag[2] count[4] - size[4] Tclunk tag[2] fid[4] - size[4] Rclunk tag[2] - size[4] Tremove tag[2] fid[4] - size[4] Rremove tag[2] - size[4] Tstat tag[2] fid[4] - size[4] Rstat tag[2] stat[n] - size[4] Twstat tag[2] fid[4] stat[n] - size[4] Rwstat tag[2] - - stat[n]: - size[2] total byte count of the following data - type[2] for kernel use - dev[4] for kernel use - qid.type[1] the type of the file (directory, etc.), - represented as a bit vector corresponding to the high 8 bits of the file's mode word. - qid.vers[4] version number for given path - qid.path[8] the file server's unique identification for the file - mode[4] permissions and flags - atime[4] last access time - mtime[4] last modification time - length[8] length of file in bytes - name[ s ] file name; must be / if the file is the root directory of the server - uid[ s ] owner name - gid[ s ] group name - muid[ s ] -*/ - -/*9P message types */ -enum { - TVERSION = 100, - RVERSION, - TAUTH = 102, - RAUTH, - TATTACH = 104, - RATTACH, - TERROR = 106, - RERROR, - TFLUSH = 108, - RFLUSH, - TWALK = 110, - RWALK, - TOPEN = 112, - ROPEN, - TCREATE = 114, - RCREATE, - TREAD = 116, - RREAD, - TWRITE = 118, - RWRITE, - TCLUNK = 120, - RCLUNK, - TREMOVE = 122, - RREMOVE, - TSTAT = 124, - RSTAT, - TWSTAT = 126, - RWSTAT, -}; - -/*borrowed from libc.h of Plan 9 */ -#define DMDIR 0x80000000 /*mode bit for directories */ -#define DMAPPEND 0x40000000 /*mode bit for append only files */ -#define DMEXCL 0x20000000 /*mode bit for exclusive use files */ -#define DMMOUNT 0x10000000 /*mode bit for mounted channel */ -#define DMAUTH 0x08000000 /*mode bit for authentication file */ -#define DMTMP 0x04000000 /*mode bit for non-backed-up file */ - -#define DMREAD 0x4<<6 /*mode bit for read permission */ -#define DMWRITE 0x2<<6 /*mode bit for write permission */ -#define DMEXEC 0x1<<6 /*mode bit for execute permission */ - -/*modes */ -enum { - IXP_OREAD = 0x00, - IXP_OWRITE = 0x01, - IXP_ORDWR = 0x02, - IXP_OEXEC = 0x03, - IXP_OEXCL = 0x04, - IXP_OTRUNC = 0x10, - IXP_OREXEC = 0x20, - IXP_ORCLOSE = 0x40, - IXP_OAPPEND = 0x80, -}; - -/*qid.types */ -enum { - IXP_QTDIR = 0x80, - IXP_QTAPPEND = 0x40, - IXP_QTEXCL = 0x20, - IXP_QTMOUNT = 0x10, - IXP_QTAUTH = 0x08, - IXP_QTTMP = 0x04, - IXP_QTSYMLINK = 0x02, - IXP_QTLINK = 0x01, - IXP_QTFILE = 0x00, -}; - -#define IXP_NOTAG (unsigned short)~0U /*Dummy tag */ -#define IXP_NOFID (unsigned int)~0 /*No auth */ - -typedef struct { - unsigned char type; - unsigned int version; - unsigned long long path; -} Qid; - -/*stat structure */ -typedef struct { - unsigned short type; - unsigned int dev; - Qid qid; - unsigned int mode; - unsigned int atime; - unsigned int mtime; - unsigned long long length; - char name[IXP_MAX_FLEN]; - char uid[IXP_MAX_ULEN]; - char gid[IXP_MAX_ULEN]; - char muid[IXP_MAX_ULEN]; -} Stat; - -typedef struct { - unsigned char id; - unsigned short tag; - unsigned int fid; - unsigned int maxmsg; /*Tversion, Rversion */ - char version[IXP_MAX_VERSION]; /*Tversion, Rversion */ - unsigned short oldtag; /*Tflush */ - char errstr[IXP_MAX_ERROR]; /*Rerror */ - Qid qid; /*Rattach, Ropen, Rcreate */ - unsigned int iounit; /*Ropen, Rcreate */ - Qid aqid; /*Rauth */ - unsigned int afid; /*Tauth, Tattach */ - char uname[IXP_MAX_ULEN]; /*Tauth, Tattach */ - char aname[IXP_MAX_FLEN]; /*Tauth, Tattach */ - unsigned int perm; /*Tcreate */ - char name[IXP_MAX_FLEN]; /*Tcreate */ - unsigned char mode; /*Tcreate, Topen */ - unsigned int newfid; /*Twalk */ - unsigned short nwname; /*Twalk */ - char wname[IXP_MAX_WELEM][IXP_MAX_FLEN]; /*Twalk */ - unsigned short nwqid; /*Rwalk */ - Qid wqid[IXP_MAX_WELEM]; /*Rwalk */ - unsigned long long offset; /*Tread, Twrite */ - unsigned int count; /*Tread, Twrite, Rread */ - Stat stat; /*Rstat */ - unsigned short nstat; /*Twstat, Rstat */ - unsigned char data[IXP_MAX_MSG]; /*Twrite, Rread, Twstat, - *Rstat */ -} Fcall; - -typedef struct IXPServer IXPServer; -typedef struct IXPConn IXPConn; -typedef struct IXPMap IXPMap; - -struct IXPMap { - unsigned int fid; - Qid qid; -}; - -struct IXPConn { - int fd; - void (*read) (IXPServer *, IXPConn *); - void (*close) (IXPServer *, IXPConn *); - IXPMap **map; - size_t mapsz; - Fcall *fcall; - Fcall **pend; - size_t pendsz; -}; - -struct IXPServer { - int running; - IXPConn **conn; - size_t connsz; - int maxfd; - fd_set rd; -}; - -typedef struct { - int fd; - unsigned int root_fid; - Qid root_qid; - Fcall fcall; - char *errstr; -} IXPClient; - -/* client.c */ -int ixp_client_init(IXPClient *c, char *address); -void ixp_client_deinit(IXPClient *c); -int ixp_client_remove(IXPClient *c, unsigned int newfid, char *filepath); -int ixp_client_create(IXPClient *c, unsigned int dirfid, char *name, - unsigned int perm, unsigned char mode); -int ixp_client_walk(IXPClient *c, unsigned int newfid, char *filepath); -int ixp_client_open(IXPClient *c, unsigned int newfid, char *filepath, - unsigned char mode); -int ixp_client_read(IXPClient *c, unsigned int fid, - unsigned long long offset, void *result, - unsigned int res_len); -int ixp_client_write(IXPClient *c, unsigned int fid, - unsigned long long offset, - unsigned int count, unsigned char *data); -int ixp_client_close(IXPClient *c, unsigned int fid); - -/* convert.c */ -void *ixp_enc_u8(unsigned char *msg, unsigned char val); -void *ixp_dec_u8(unsigned char *msg, unsigned char *val); -void *ixp_enc_u16(unsigned char *msg, unsigned short val); -void *ixp_dec_u16(unsigned char *msg, unsigned short *val); -void *ixp_enc_u32(unsigned char *msg, unsigned int val); -void *ixp_dec_u32(unsigned char *msg, unsigned int *val); -void *ixp_enc_u64(unsigned char *msg, unsigned long long val); -void *ixp_dec_u64(unsigned char *msg, unsigned long long *val); -void *ixp_enc_string(unsigned char *msg, const char *s); -void *ixp_dec_string(unsigned char *msg, char *string, - unsigned short stringlen, unsigned short *len); -void *ixp_enc_data(unsigned char *msg, unsigned char *data, - unsigned int datalen); -void *ixp_dec_data(unsigned char *msg, unsigned char *data, - unsigned int datalen); -void *ixp_enc_prefix(unsigned char *msg, unsigned int size, - unsigned char id, unsigned short tag); -void *ixp_dec_prefix(unsigned char *msg, unsigned int *size, - unsigned char *id, unsigned short *tag); -void *ixp_enc_qid(unsigned char *msg, Qid *qid); -void *ixp_dec_qid(unsigned char *msg, Qid *qid); -void *ixp_enc_stat(unsigned char *msg, Stat *stat); -void *ixp_dec_stat(unsigned char *msg, Stat *stat); - -/* message.c */ -unsigned short ixp_sizeof_stat(Stat *stat); -unsigned int ixp_fcall_to_msg(Fcall *fcall, void *msg, unsigned int msglen); -unsigned int ixp_msg_to_fcall(void *msg, unsigned int msglen, Fcall *fcall); - -/* server.c */ -char *ixp_server_loop(IXPServer *s); -IXPMap *ixp_server_fid2map(IXPConn *c, unsigned int fid); - -/* socket.c */ -int ixp_connect_sock(char *address); -int ixp_accept_sock(int fd); -int ixp_create_sock(char *address, char **errstr); - -/* transport.c */ -unsigned int ixp_send_message(int fd, void *msg, unsigned int msize, char **errstr); -unsigned int ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr); diff --git a/libixp2/message.c b/libixp2/message.c @@ -1,317 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "ixp.h" - -#define IXP_QIDSZ (sizeof(unsigned char) + sizeof(unsigned int)\ - + sizeof(unsigned long long)) - -static unsigned short -sizeof_string(const char *s) -{ - return sizeof(unsigned short) + strlen(s); -} - -unsigned short -ixp_sizeof_stat(Stat * stat) -{ - return IXP_QIDSZ - + 2 * sizeof(unsigned short) - + 4 * sizeof(unsigned int) - + sizeof(unsigned long long) - + sizeof_string(stat->name) - + sizeof_string(stat->uid) - + sizeof_string(stat->gid) - + sizeof_string(stat->muid); -} - -unsigned int -ixp_fcall_to_msg(Fcall * fcall, void *msg, unsigned int msglen) -{ - unsigned int i, msize = - sizeof(unsigned char) + sizeof(unsigned short) + - sizeof(unsigned int); - void *p = msg; - - switch (fcall->id) { - case TVERSION: - case RVERSION: - msize += sizeof(unsigned int) + sizeof_string(fcall->version); - break; - case TAUTH: - msize += - sizeof(unsigned int) + sizeof_string(fcall->uname) + - sizeof_string(fcall->aname); - break; - case RAUTH: - case RATTACH: - msize += IXP_QIDSZ; - break; - case TATTACH: - msize += - 2 * sizeof(unsigned int) + sizeof_string(fcall->uname) + - sizeof_string(fcall->aname); - break; - case RERROR: - msize += sizeof_string(fcall->errstr); - break; - case RWRITE: - case TCLUNK: - case TREMOVE: - case TSTAT: - msize += sizeof(unsigned int); - break; - case TWALK: - msize += sizeof(unsigned short) + 2 * sizeof(unsigned int); - for(i = 0; i < fcall->nwname; i++) - msize += sizeof_string(fcall->wname[i]); - break; - case TFLUSH: - msize += sizeof(unsigned short); - break; - case RWALK: - msize += sizeof(unsigned short) + fcall->nwqid * IXP_QIDSZ; - break; - case TOPEN: - msize += sizeof(unsigned int) + sizeof(unsigned char); - break; - case ROPEN: - case RCREATE: - msize += IXP_QIDSZ + sizeof(unsigned int); - break; - case TCREATE: - msize += - sizeof(unsigned char) + 2 * sizeof(unsigned int) + - sizeof_string(fcall->name); - break; - case TREAD: - msize += 2 * sizeof(unsigned int) + sizeof(unsigned long long); - break; - case RREAD: - msize += sizeof(unsigned int) + fcall->count; - break; - case TWRITE: - msize += - 2 * sizeof(unsigned int) + sizeof(unsigned long long) + - fcall->count; - break; - case RSTAT: - msize += sizeof(unsigned short) + ixp_sizeof_stat(&fcall->stat); - break; - case TWSTAT: - msize += sizeof(unsigned int) + sizeof(unsigned short) + ixp_sizeof_stat(&fcall->stat); - break; - default: - break; - } - - if(msize > msglen) - return 0; - p = ixp_enc_prefix(p, msize, fcall->id, fcall->tag); - - switch (fcall->id) { - case TVERSION: - case RVERSION: - p = ixp_enc_u32(p, fcall->maxmsg); - p = ixp_enc_string(p, fcall->version); - break; - case TAUTH: - p = ixp_enc_u32(p, fcall->afid); - p = ixp_enc_string(p, fcall->uname); - p = ixp_enc_string(p, fcall->aname); - break; - case RAUTH: - p = ixp_enc_qid(p, &fcall->aqid); - break; - case RATTACH: - p = ixp_enc_qid(p, &fcall->qid); - break; - case TATTACH: - p = ixp_enc_u32(p, fcall->fid); - p = ixp_enc_u32(p, fcall->afid); - p = ixp_enc_string(p, fcall->uname); - p = ixp_enc_string(p, fcall->aname); - break; - case RERROR: - p = ixp_enc_string(p, fcall->errstr); - break; - case TFLUSH: - p = ixp_enc_u16(p, fcall->oldtag); - break; - case TWALK: - p = ixp_enc_u32(p, fcall->fid); - p = ixp_enc_u32(p, fcall->newfid); - p = ixp_enc_u16(p, fcall->nwname); - for(i = 0; i < fcall->nwname; i++) - p = ixp_enc_string(p, fcall->wname[i]); - break; - case RWALK: - p = ixp_enc_u16(p, fcall->nwqid); - for(i = 0; i < fcall->nwqid; i++) - p = ixp_enc_qid(p, &fcall->wqid[i]); - break; - case TOPEN: - p = ixp_enc_u32(p, fcall->fid); - p = ixp_enc_u8(p, fcall->mode); - break; - case ROPEN: - case RCREATE: - p = ixp_enc_qid(p, &fcall->qid); - p = ixp_enc_u32(p, fcall->iounit); - break; - case TCREATE: - p = ixp_enc_u32(p, fcall->fid); - p = ixp_enc_string(p, fcall->name); - p = ixp_enc_u32(p, fcall->perm); - p = ixp_enc_u8(p, fcall->mode); - break; - case TREAD: - p = ixp_enc_u32(p, fcall->fid); - p = ixp_enc_u64(p, fcall->offset); - p = ixp_enc_u32(p, fcall->count); - break; - case RREAD: - p = ixp_enc_u32(p, fcall->count); - p = ixp_enc_data(p, fcall->data, fcall->count); - break; - case TWRITE: - p = ixp_enc_u32(p, fcall->fid); - p = ixp_enc_u64(p, fcall->offset); - p = ixp_enc_u32(p, fcall->count); - p = ixp_enc_data(p, fcall->data, fcall->count); - break; - case RWRITE: - p = ixp_enc_u32(p, fcall->count); - break; - case TCLUNK: - case TREMOVE: - case TSTAT: - p = ixp_enc_u32(p, fcall->fid); - break; - case RSTAT: - p = ixp_enc_u16(p, ixp_sizeof_stat(&fcall->stat)); - p = ixp_enc_stat(p, &fcall->stat); - break; - case TWSTAT: - p = ixp_enc_u32(p, fcall->fid); - p = ixp_enc_u16(p, ixp_sizeof_stat(&fcall->stat)); - p = ixp_enc_stat(p, &fcall->stat); - break; - } - - if(msg + msize == p) - return msize; - return 0; -} - -unsigned int -ixp_msg_to_fcall(void *msg, unsigned int msglen, Fcall * fcall) -{ - unsigned int i, msize; - unsigned short len; - void *p = ixp_dec_prefix(msg, &msize, &fcall->id, &fcall->tag); - - if(msize > msglen) /* bad message */ - return 0; - - switch (fcall->id) { - case TVERSION: - case RVERSION: - p = ixp_dec_u32(p, &fcall->maxmsg); - p = ixp_dec_string(p, fcall->version, sizeof(fcall->version), &len); - break; - case TAUTH: - p = ixp_dec_u32(p, &fcall->afid); - p = ixp_dec_string(p, fcall->uname, sizeof(fcall->uname), &len); - p = ixp_dec_string(p, fcall->aname, sizeof(fcall->aname), &len); - break; - case RAUTH: - p = ixp_dec_qid(p, &fcall->aqid); - break; - case RATTACH: - p = ixp_dec_qid(p, &fcall->qid); - break; - case TATTACH: - p = ixp_dec_u32(p, &fcall->fid); - p = ixp_dec_u32(p, &fcall->afid); - p = ixp_dec_string(p, fcall->uname, sizeof(fcall->uname), &len); - p = ixp_dec_string(p, fcall->aname, sizeof(fcall->aname), &len); - break; - case RERROR: - p = ixp_dec_string(p, fcall->errstr, sizeof(fcall->errstr), &len); - break; - case TFLUSH: - p = ixp_dec_u16(p, &fcall->oldtag); - break; - case TWALK: - p = ixp_dec_u32(p, &fcall->fid); - p = ixp_dec_u32(p, &fcall->newfid); - p = ixp_dec_u16(p, &fcall->nwname); - for(i = 0; i < fcall->nwname; i++) { - - p = ixp_dec_string(p, fcall->wname[i], IXP_MAX_FLEN, &len); - } - break; - case RWALK: - p = ixp_dec_u16(p, &fcall->nwqid); - for(i = 0; i < fcall->nwqid; i++) - p = ixp_dec_qid(p, &fcall->wqid[i]); - break; - case TOPEN: - p = ixp_dec_u32(p, &fcall->fid); - p = ixp_dec_u8(p, &fcall->mode); - break; - case ROPEN: - case RCREATE: - p = ixp_dec_qid(p, &fcall->qid); - p = ixp_dec_u32(p, &fcall->iounit); - break; - case TCREATE: - p = ixp_dec_u32(p, &fcall->fid); - p = ixp_dec_string(p, fcall->name, sizeof(fcall->name), &len); - p = ixp_dec_u32(p, &fcall->perm); - p = ixp_dec_u8(p, &fcall->mode); - break; - case TREAD: - p = ixp_dec_u32(p, &fcall->fid); - p = ixp_dec_u64(p, &fcall->offset); - p = ixp_dec_u32(p, &fcall->count); - break; - case RREAD: - p = ixp_dec_u32(p, &fcall->count); - p = ixp_dec_data(p, fcall->data, fcall->count); - break; - case TWRITE: - p = ixp_dec_u32(p, &fcall->fid); - p = ixp_dec_u64(p, &fcall->offset); - p = ixp_dec_u32(p, &fcall->count); - p = ixp_dec_data(p, fcall->data, fcall->count); - break; - case RWRITE: - p = ixp_dec_u32(p, &fcall->count); - break; - case TCLUNK: - case TREMOVE: - case TSTAT: - p = ixp_dec_u32(p, &fcall->fid); - break; - case RSTAT: - p = ixp_dec_u16(p, &len); - p = ixp_dec_stat(p, &fcall->stat); - break; - case TWSTAT: - p = ixp_dec_u32(p, &fcall->fid); - p = ixp_dec_u16(p, &len); - p = ixp_dec_stat(p, &fcall->stat); - break; - } - - if(msg + msize == p) - return msize; - return 0; -} diff --git a/libixp2/server.c b/libixp2/server.c @@ -1,73 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> - -#include "ixp.h" -#include "cext.h" - -static void -prepare_select(IXPServer *s) -{ - int i; - FD_ZERO(&s->rd); - for(i = 0; (i < s->connsz) && s->conn[i]; i++) { - if(s->maxfd < s->conn[i]->fd) - s->maxfd = s->conn[i]->fd; - if(s->conn[i]->read) - FD_SET(s->conn[i]->fd, &s->rd); - } -} - -static void -handle_conns(IXPServer *s) -{ - int i; - for(i = 0; (i < s->connsz) && s->conn[i]; i++) - if(FD_ISSET(s->conn[i]->fd, &s->rd) && s->conn[i]->read) - /* call read handler */ - s->conn[i]->read(s, s->conn[i]); -} - -char * -ixp_server_loop(IXPServer *s) -{ - int r; - s->running = 1; - - /* main loop */ - while(s->running && s->conn) { - - prepare_select(s); - - r = select(s->maxfd + 1, &s->rd, 0, 0, 0); - if(r == -1 && errno == EINTR) - continue; - if(r < 0) - return "fatal select error"; - else if(r > 0) - handle_conns(s); - } - return nil; -} - -IXPMap * -ixp_server_fid2map(IXPConn *c, unsigned int fid) -{ - size_t i; - for(i = 0; (i < c->mapsz) && c->map[i]; i++) - if(c->map[i]->fid == fid) - return c->map[i]; - return nil; -} diff --git a/libixp2/socket.c b/libixp2/socket.c @@ -1,204 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <netinet/in.h> -#include <netdb.h> -#include <sys/un.h> -#include <unistd.h> - -#include "cext.h" -#include "ixp.h" - -static int -connect_unix_sock(char *address) -{ - int fd = 0; - struct sockaddr_un addr = { 0 }; - socklen_t su_len; - - /* init */ - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, address, sizeof(addr.sun_path)); - su_len = sizeof(struct sockaddr) + strlen(addr.sun_path); - - if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) - return -1; - if(connect(fd, (struct sockaddr *) &addr, su_len)) { - close(fd); - return -1; - } - return fd; -} - -static int -connect_inet_sock(char *host) -{ - int fd = 0; - struct sockaddr_in addr = { 0 }; - struct hostent *hp; - char *port = strrchr(host, '!'); - const char *errstr = nil; - unsigned int prt; - - *port = 0; - port++; - prt = cext_strtonum(port, 1024, 65535, &errstr); - if(errstr) - return -1; - - /* init */ - if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) - return -1; - hp = gethostbyname(host); - addr.sin_family = AF_INET; - addr.sin_port = htons(prt); - bcopy(hp->h_addr, &addr.sin_addr, hp->h_length); - - if(connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))) { - close(fd); - return -1; - } - return fd; -} - -int -ixp_connect_sock(char *address) -{ - char *p = strchr(address, '!'); - char *addr, *type; - - if(!p) - return -1; - *p = 0; - - addr = &p[1]; - type = address; /* unix, inet */ - - if(!strncmp(type, "unix", 5)) - return connect_unix_sock(addr); - else if(!strncmp(type, "tcp", 4)) - return connect_inet_sock(addr); - return -1; -} - -int -ixp_accept_sock(int fd) -{ - socklen_t su_len; - struct sockaddr_un addr = { 0 }; - - su_len = sizeof(struct sockaddr); - return accept(fd, (struct sockaddr *) &addr, &su_len); -} - -static int -create_inet_sock(char *host, char **errstr) -{ - int fd; - struct sockaddr_in addr = { 0 }; - char *port = strrchr(host, '!'); - unsigned int prt; - - if(!port) { - *errstr = "no port provided in address"; - return -1; - } - *port = 0; - port++; - prt = cext_strtonum(port, 1024, 65535, (const char **)errstr); - if(*errstr) - return -1; - signal(SIGPIPE, SIG_IGN); - if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - *errstr = "cannot open socket"; - return -1; - } - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl(INADDR_ANY); - addr.sin_port = htons(prt); - - if(bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0) { - *errstr = "cannot bind socket"; - close(fd); - return -1; - } - - if(listen(fd, IXP_MAX_CACHE) < 0) { - *errstr = "cannot listen on socket"; - close(fd); - return -1; - } - return fd; -} - -static int -create_unix_sock(char *file, char **errstr) -{ - int fd; - int yes = 1; - struct sockaddr_un addr = { 0 }; - socklen_t su_len; - - signal(SIGPIPE, SIG_IGN); - if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { - *errstr = "cannot open socket"; - return -1; - } - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, - (char *) &yes, sizeof(yes)) < 0) { - *errstr = "cannot set socket options"; - close(fd); - return -1; - } - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, file, sizeof(addr.sun_path)); - su_len = sizeof(struct sockaddr) + strlen(addr.sun_path); - - unlink(file); /* remove old socket, if any */ - if(bind(fd, (struct sockaddr *) &addr, su_len) < 0) { - *errstr = "cannot bind socket"; - close(fd); - return -1; - } - chmod(file, S_IRWXU); - - if(listen(fd, IXP_MAX_CACHE) < 0) { - *errstr = "cannot listen on socket"; - close(fd); - return -1; - } - return fd; -} - -int -ixp_create_sock(char *address, char **errstr) -{ - char *p = strchr(address, '!'); - char *addr, *type; - - if(!p) { - *errstr = "no socket type defined"; - return -1; - } - *p = 0; - - addr = &p[1]; - type = address; /* unix, inet */ - - if(!strncmp(type, "unix", 5)) - return create_unix_sock(addr, errstr); - else if(!strncmp(type, "tcp", 4)) - return create_inet_sock(addr, errstr); - else - *errstr = "unkown socket type"; - return -1; -} diff --git a/libixp2/transport.c b/libixp2/transport.c @@ -1,81 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <unistd.h> - -#include "ixp.h" - -#include <cext.h> - -unsigned int -ixp_send_message(int fd, void *msg, unsigned int msize, char **errstr) -{ - unsigned int num = 0; - int r; - - /* send message */ - while(num < msize) { - r = write(fd, msg + num, msize - num); - if(r == -1 && errno == EINTR) - continue; - if(r < 1) { - *errstr = "cannot send message"; - return 0; - } - num += r; - } - return num; -} - -static unsigned int -ixp_recv_data(int fd, void *msg, unsigned int msize, char **errstr) -{ - unsigned int num = 0; - int r = 0; - - /* receive data */ - while(num < msize) { - r = read(fd, msg + num, msize - num); - if(r == -1 && errno == EINTR) - continue; - if(r < 1) { - *errstr = "cannot receive data"; - return 0; - } - num += r; - } - return num; -} - -unsigned int -ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr) -{ - unsigned int msize; - - /* receive header */ - if(ixp_recv_data(fd, msg, sizeof(unsigned int), errstr) != - sizeof(unsigned int)) - return 0; - ixp_dec_u32(msg, &msize); - if(msize > msglen) { - *errstr = "message size exceeds buffer size"; - return 0; - } - /* receive message */ - if(ixp_recv_data - (fd, msg + sizeof(unsigned int), msize - sizeof(unsigned int), - errstr) - != msize - sizeof(unsigned int)) - return 0; - return msize; -} diff --git a/libwmii/Makefile b/libwmii/Makefile @@ -6,7 +6,7 @@ include ../config.mk CFLAGS += -I../liblitz -I../libixp -I../libcext LDFLAGS += -L../liblitz -llitz -L../libixp -lixp -L../libcext -lcext -SRC = ixputil.c spawn.c wm.c +SRC = spawn.c wm.c OBJ = ${SRC:.c=.o} diff --git a/libwmii/ixputil.c b/libwmii/ixputil.c @@ -1,98 +0,0 @@ -/* - * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com> - * See LICENSE file for license details. - */ - -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include "wmii.h" - -static pid_t mypid; -static char *mysockfile; - -File * -wmii_create_ixpfile(IXPServer * s, char *key, char *val) -{ - File *f = ixp_create(s, key); - if(f && !is_directory(f)) { - size_t l = val ? strlen(val) : 0; - f->content = l ? strdup(val) : 0; - f->size = l; - return f; - } - /* forbidden, file is directory */ - return 0; -} - -void -wmii_get_ixppath(File * f, char *path, size_t size) -{ - char buf[512]; - - buf[0] = 0; - if(path) - cext_strlcpy(buf, path, sizeof(buf)); - snprintf(path, size, "%s/", f->name); - if(buf[0] != 0) - cext_strlcat(path, buf, size); - if(f->parent) - wmii_get_ixppath(f->parent, path, size); -} - -void -wmii_move_ixpfile(File * f, File * to_parent) -{ - File *p = f->parent; - File *fil = p->content; - - /* detach */ - if(p->content == f) - p->content = fil->next; - else { - while(fil->next != f) - fil = fil->next; - fil->next = f->next; - } - f->next = 0; - - - /* attach */ - if(!to_parent->content) - to_parent->content = f; - else { - for(fil = to_parent->content; fil->next; fil = fil->next); - fil->next = f; - } - f->parent = to_parent; -} - -static void -exit_cleanup() -{ - if(mypid == getpid()) - unlink(mysockfile); -} - -IXPServer * -wmii_setup_server(char *sockfile) -{ - IXPServer *s; - - if(!sockfile) { - fprintf(stderr, "%s\n", "libwmii: no socket file provided"); - exit(1); - } - mysockfile = sockfile; - mypid = getpid(); - s = init_server(sockfile, exit_cleanup); - if(!s) { - perror("libwmii: cannot initialize IXP server"); - exit(1); - } - return s; -} diff --git a/libwmii/wmii.h b/libwmii/wmii.h @@ -16,12 +16,6 @@ struct Action { void (*func) (void *obj, char *); }; -/* ixputil.c */ -File *wmii_create_ixpfile(IXPServer * s, char *key, char *val); -void wmii_get_ixppath(File * f, char *path, size_t size); -void wmii_move_ixpfile(File * f, File * to_parent); -IXPServer *wmii_setup_server(char *sockfile); - /* spawn.c */ void wmii_spawn(void *dpy, char *cmd);