[debian] Fix DESTDIR. Fix some lintian warnings.
1 /* Copyright ©2007 Ron Minnich <rminnich at gmail dot com>
2 /* Copyright ©2007-2010 Kris Maglione <maglione.k@gmail.com>
3 * See LICENSE file for license details.
6 /* This is a simple 9P file server which serves a normal filesystem
7 * hierarchy. While some of the code is from wmii, the server is by
10 * Note: I added an ifdef for Linux vs. BSD for the mount call, so
11 * this compiles on BSD, but it won't actually run. It should,
12 * ideally, have the option of not mounting the FS.
24 #include <sys/param.h>
25 #include <sys/mount.h>
26 #include <sys/socket.h>
28 #include <sys/types.h>
32 #include <ixp_local.h>
35 #define fatal(...) ixp_eprint("ixpsrv: fatal: " __VA_ARGS__)
36 #define debug(...) if(debuglevel) fprintf(stderr, "ixpsrv: " __VA_ARGS__)
39 typedef struct FidAux FidAux;
43 char name[]; /* c99 */
48 Enoperm[] = "permission denied",
49 Enofile[] = "file not found",
50 Ebadvalue[] = "bad value";
52 #define QID(t, i) ((vlong)(t))
55 static IxpServer server;
57 static int debuglevel = 0;
59 static void fs_open(Ixp9Req *r);
60 static void fs_walk(Ixp9Req *r);
61 static void fs_read(Ixp9Req *r);
62 static void fs_stat(Ixp9Req *r);
63 static void fs_write(Ixp9Req *r);
64 static void fs_clunk(Ixp9Req *r);
65 static void fs_flush(Ixp9Req *r);
66 static void fs_attach(Ixp9Req *r);
67 static void fs_create(Ixp9Req *r);
68 static void fs_remove(Ixp9Req *r);
69 static void fs_freefid(IxpFid *f);
88 "usage: %1$s [-a <address>] {create | read | ls [-ld] | remove | write} <file>\n"
89 " %1$s [-a <address>] xwrite <file> <data>\n"
95 /* Utility Functions */
98 newfidaux(char *name) {
101 f = ixp_emallocz(sizeof(*f) + strlen(name) + 1);
103 strcpy(f->name, name);
107 /* -1 means it ain't anything .. */
112 if (stat(path, &buf) < 0)
115 return S_ISDIR(buf.st_mode);
118 /* This should be moved to libixp */
120 write_buf(Ixp9Req *r, char *buf, uint len) {
122 if(r->ifcall.tread.offset >= len)
125 len -= r->ifcall.tread.offset;
126 if(len > r->ifcall.tread.count)
127 len = r->ifcall.tread.count;
128 r->ofcall.rread.data = ixp_emalloc(len);
129 memcpy(r->ofcall.rread.data, buf + r->ifcall.tread.offset, len);
130 r->ofcall.rread.count = len;
134 /* This should be moved to libixp */
136 write_to_buf(Ixp9Req *r, void *buf, uint *len, uint max) {
139 // offset = (r->fid->omode&OAPPEND) ? *len : r->ifcall.tread.offset;
140 offset = r->ifcall.tread.offset;
141 if(offset > *len || r->ifcall.tread.count == 0) {
142 r->ofcall.rread.count = 0;
146 count = r->ifcall.tread.count;
147 if(max && (count > max - offset))
148 count = max - offset;
150 *len = offset + count;
153 *(void **)buf = ixp_erealloc(*(void **)buf, *len + 1);
157 memcpy((uchar*)buf + offset, r->ifcall.tread.data, count);
158 r->ofcall.rread.count = count;
159 ((char *)buf)[offset+count] = '\0';
163 dostat(Stat *s, char *name, struct stat *buf) {
167 s->qid.type = buf->st_mode&S_IFMT;
168 s->qid.path = buf->st_ino;
170 s->mode = buf->st_mode & 0777;
171 if (S_ISDIR(buf->st_mode)) {
173 s->qid.type |= QTDIR;
175 s->atime = buf->st_atime;
176 s->mtime = buf->st_mtime;
177 s->length = buf->st_size;
184 /* the gnu/linux guys have made a real mess of errno ... don't ask --ron */
185 /* I agree. --Kris */
187 rerrno(Ixp9Req *r, char *m) {
190 respond(r, strerror_r(errno, errbuf, sizeof(errbuf)));
196 fs_attach(Ixp9Req *r) {
198 debug("fs_attach(%p)\n", r);
200 r->fid->qid.type = QTDIR;
201 r->fid->qid.path = (uintptr_t)r->fid;
202 r->fid->aux = newfidaux("/");
203 r->ofcall.rattach.qid = r->fid->qid;
208 fs_walk(Ixp9Req *r) {
214 debug("fs_walk(%p)\n", r);
217 name = malloc(PATH_MAX);
218 strcpy(name, f->name);
219 if (stat(name, &buf) < 0){
224 /* build full path. Stat full path. Done */
225 for(i=0; i < r->ifcall.twalk.nwname; i++) {
227 strcat(name, r->ifcall.twalk.wname[i]);
228 if (stat(name, &buf) < 0){
233 r->ofcall.rwalk.wqid[i].type = buf.st_mode&S_IFMT;
234 r->ofcall.rwalk.wqid[i].path = buf.st_ino;
237 r->newfid->aux = newfidaux(name);
238 r->ofcall.rwalk.nwqid = i;
244 fs_stat(Ixp9Req *r) {
254 debug("fs_stat(%p)\n", r);
255 debug("fs_stat %s\n", f->name);
258 if (stat(name, &st) < 0){
263 dostat(&s, name, &st);
265 r->ofcall.rstat.nstat = size = ixp_sizeof_stat(&s);
267 buf = ixp_emallocz(size);
269 m = ixp_message(buf, size, MsgPack);
272 r->ofcall.rstat.stat = m.data;
277 fs_read(Ixp9Req *r) {
283 debug("fs_read(%p)\n", r);
292 size = r->ifcall.tread.count;
293 buf = ixp_emallocz(size);
294 m = ixp_message((uchar*)buf, size, MsgPack);
296 /* note: we don't really handle lots of things well, so do one thing
299 /*for(f=f->next; f; f=f->next) */{
304 stat(d->d_name, &st);
305 dostat(&s, d->d_name, &st);
306 n = ixp_sizeof_stat(&s);
311 r->ofcall.rread.count = n;
312 r->ofcall.rread.data = (char*)m.data;
316 r->ofcall.rread.data = ixp_emallocz(r->ifcall.tread.count);
317 if (! r->ofcall.rread.data) {
321 r->ofcall.rread.count = pread(f->fd, r->ofcall.rread.data, r->ifcall.tread.count, r->ifcall.tread.offset);
322 if (r->ofcall.rread.count < 0)
330 * This is an assert because this should this should not be called if
331 * the file is not open for reading.
333 assert(!"Read called on an unreadable file");
337 fs_write(Ixp9Req *r) {
340 debug("fs_write(%p)\n", r);
342 if(r->ifcall.twrite.count == 0) {
348 * This is an assert because this function should not be called if
349 * the file is not open for writing.
351 assert(!"Write called on an unwritable file");
355 fs_open(Ixp9Req *r) {
359 debug("fs_open(%p)\n", r);
362 dir = isdir(f->name);
363 /* fucking stupid linux -- open dir is a DIR */
366 f->dir = opendir(f->name);
372 f->fd = open(f->name, O_RDONLY);
383 fs_create(Ixp9Req *r) {
384 debug("fs_create(%p)\n", r);
389 fs_remove(Ixp9Req *r) {
390 debug("fs_remove(%p)\n", r);
396 fs_clunk(Ixp9Req *r) {
400 debug("fs_clunk(%p)\n", f);
403 dir = isdir(f->name);
405 (void) closedir(f->dir);
416 fs_flush(Ixp9Req *r) {
417 debug("fs_flush(%p)\n", r);
423 debug("fs_freefid(%p)\n", f);
427 // mount -t 9p 127.1 /tmp/cache -o port=20006,noextend
429 #if defined(__linux__)
430 # define MF(n) MS_##n
431 # define mymount(src, dest, flags, opts) mount(src, dest, "9p", flags, opts)
432 #elif defined(__FreeBSD__) || defined(__OpenBSD__)
433 # define MF(n) MNT_##n
434 # define mymount(src, dest, flags, opts) mount("9p", dest, flags, src)
437 static ulong mountflags =
440 /* | MF(NODIRATIME) */
446 getaddr(char *mountaddr, char **ip, char **port) {
450 mountaddr = getenv("XCPU_PARENT");
455 if (strcmp(cp, "tcp!"))
460 cp = strstr(cp, "!");
463 return strtoul(*port, 0, 0);
467 main(int argc, char *argv[]) {
470 int domount, mountonly;
478 address = getenv("IXP_ADDRESS");
483 printf("%s-" VERSION ", ©2007 Ron Minnich\n", argv0);
486 address = EARGF(usage());
502 fatal("$IXP_ADDRESS not set\n");
504 if(!(user = getenv("USER")))
505 fatal("$USER not set\n");
507 fd = ixp_announce(address);
509 fatal("%s\n", errstr);
511 /* set up a fake client so we can grap connects. */
512 acceptor = ixp_listen(&server, fd, &p9srv, serve_9pcon, NULL);
514 /* we might need to mount ourselves. The bit of complexity is the need to fork so
515 * we can serve ourselves. We've done the listen so that's ok.
526 port = getaddr(mountaddr, &addr, &aport);
527 sprintf(options, "port=%d,noextend", port);
528 if (mymount(addr, "/tmp/cache", mountflags, options) < 0)
529 errx(1, "Mount failed");
537 ixp_serverloop(&server);
538 printf("msg %s\n", ixp_errbuf());