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

This commit is contained in:
Anselm R. Garbe 2006-01-30 20:08:58 +02:00
parent f137735249
commit df407fd8cd
25 changed files with 981 additions and 2763 deletions

View File

@ -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

View File

@ -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 \

View File

@ -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;
}

View File

@ -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();

View File

@ -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);

View File

@ -18,7 +18,7 @@
#include <X11/Xutil.h>
#include <sys/socket.h>
#include "../libixp2/ixp.h"
#include "ixp.h"
#include "blitz.h"
/*

View File

@ -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;
void *data = cext_emallocz(c.fcall.iounit);
unsigned long long offset = 0;
size_t len = 0;
if(!action)
return;
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);
}
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;
}
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;
}
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;
}
/* 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(!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();
if(c->errstr) {
deinit_client(c);
exit_code = 1;
}
return exit_code;
/* close socket */
ixp_client_deinit(&c);
return 0;
}

View File

@ -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;
}

View File

@ -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 $<

View File

@ -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)
static int
do_fcall(IXPClient * c)
{
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));
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 void handle_dead_server(IXPClient * c)
int
ixp_client_init(IXPClient * c, char *sockfile)
{
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;
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 void *poll_server(IXPClient * c, void *request, size_t req_len,
size_t * out_len)
int
ixp_client_remove(IXPClient * c, unsigned int newfid, char *filepath)
{
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;
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);
}
static void cixp_create(IXPClient * c, char *path)
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 = 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);
/* 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 int cixp_open(IXPClient * c, char *path)
int
ixp_client_walk(IXPClient * c, unsigned int newfid, char *filepath)
{
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;
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);
}
static size_t
cixp_read(IXPClient * c, int fd, void *out_buf, size_t out_buf_len)
int
ixp_client_open(IXPClient * c, unsigned int newfid, char *filepath,
unsigned char mode)
{
size_t len;
if(ixp_client_walk(c, newfid, filepath) == -1)
return -1;
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;
/* open */
c->fcall.id = TOPEN;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = newfid;
c->fcall.mode = mode;
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_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 = tread_message(fd, offset, out_buf_len, &req_len);
void *result = poll_server(c, req, req_len, &res_len);
unsigned int bytes = c->fcall.iounit;
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;
/* 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_write(IXPClient * c, int fd, void *content, size_t in_len)
int
ixp_client_write(IXPClient * c, unsigned int fid,
unsigned long long offset, unsigned int count,
unsigned char *data)
{
seek_write(c, fd, offsets[fd][1], content, in_len);
if (!c->errstr)
offsets[fd][1] += in_len;
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
seek_write(IXPClient * c, int fd, size_t offset, void *content,
size_t in_len)
ixp_client_deinit(IXPClient * c)
{
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);
}
static void cixp_close(IXPClient * c, int fd)
{
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;
}
static void cixp_remove(IXPClient * c, char *path)
{
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);
}
IXPClient *init_ixp_client(char *sockfile)
{
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;
}
void deinit_client(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);
}
}

View File

@ -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;
/*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 int IXPRequest;
typedef int IXPResponse;
typedef enum {
HALT, SHUTDOWN, RUNNING
} IXPRunlevel;
typedef struct IXPConn IXPConn;
typedef struct IXPMap IXPMap;
struct ReqHeader {
IXPRequest req;
int fd;
size_t offset;
size_t buf_len;
struct IXPMap {
unsigned int fid;
Qid qid;
};
struct ResHeader {
IXPResponse res;
int fd;
size_t buf_len;
};
/** 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];
};
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 *);
};
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);
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);
/* 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 */
char *ixp_server_loop(IXPServer *s);
IXPMap *ixp_server_fid2map(IXPConn *c, unsigned int fid);
/* 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);
/* 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);

View File

@ -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;
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;
}
void *twrite_message(int fd, size_t offset, 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;
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;
unsigned short len;
void *p = ixp_dec_prefix(msg, &msize, &fcall->id, &fcall->tag);
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;
}
if(msize > msglen) /* bad message */
return 0;
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;
}
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 *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;
}
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 *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;
}
void *rread_message(void *content, size_t content_len, size_t * msg_len)
{
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;
}
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;
}
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;
}
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;
}
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;
}

View File

@ -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;
}

View File

@ -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)
static void
prepare_select(IXPServer *s)
{
if (s->errstr)
free(s->errstr);
if (errstr)
s->errstr = strdup(errstr);
else
s->errstr = 0;
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);
}
}
File *fd_to_file(IXPServer * s, int fd)
static void
handle_conns(IXPServer *s)
{
int cidx = fd / MAX_CONN;
int fidx = fd - (cidx * MAX_CONN);
return s->conn[cidx].files[fidx];
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]);
}
static void handle_ixp_create(Connection * c)
char *
ixp_server_loop(IXPServer *s)
{
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;
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;
}
static void handle_ixp_open(Connection * c)
IXPMap *
ixp_server_fid2map(IXPConn *c, unsigned int fid)
{
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)
{
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;
}
void
run_server_with_fd_support(IXPServer * s, int fd,
void (*fd_read) (Connection *),
void (*fd_write) (Connection *))
{
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);
}
void run_server(IXPServer * s)
{
int r, i;
s->runlevel = RUNNING;
/* main loop */
while (s->runlevel != HALT) {
update_conns(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);
}
}
}
void deinit_server(IXPServer * s)
{
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;
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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}

View File

@ -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;
}

View File

@ -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);