HEAD: remove ridiculous dependency of wvmapi (actually wvtnef) on evolution
[wvapps.git] / funfs / funfs.cc
blobf58865b49bd297c7045491ef9b9b0f505f1c5da4
1 #include "funfs.h"
2 #include "funfscodecs.h"
4 // Only used for cachefs message type translation
5 #include "cachefs.h"
7 #include <wvtcp.h>
8 #include <wvistreamlist.h>
11 #define BUFREAD(x) \
12 memcpy(&x, xinbuf.get(sizeof(x)), sizeof(x)); \
13 if (sizeof(x) == 2) \
14 SWAP16(&x); \
15 if (sizeof(x) == 4) \
16 SWAP32(&x); \
17 if (sizeof(x) == 8) \
18 SWAP64(&x)
21 #define CHECKERROR() \
22 { \
23 uint16 errcode; \
24 BUFREAD(errcode); \
25 if (errcode) \
26 { RETURN(-errcode); } \
30 #define MAYBECHECKERROR() \
31 { \
32 if (xinbuf.used() == sizeof(uint16)) \
33 { CHECKERROR(); } \
37 #define RETURN(x) \
38 if (!reply_ready) \
39 alarm(0); \
40 return x
43 #define PUTPATH(x) \
44 xoutbuf.putstr(x); \
45 xoutbuf.putch('\n')
48 #define CONTINUE_SELECT() \
49 do { \
50 context->continue_select(-1); \
51 } while (!context->alarm_was_ticking)
54 uint16 FunFS::jobid = 1;
57 FunFS::FunFS(UniConf _cfg)
58 : WvStreamClone(NULL), mycloned((WvTCPConn*)cloned),
59 log("FunFS", WvLog::Info), jobmap(255), cfg(_cfg)
61 ok = true;
62 reply_ready = false;
63 uses_continue_select = true;
65 cloned = new WvTCPConn(cfg["Hostname"].get(), cfg["Port"].getint());
66 WvIStreamList::globallist.append(this, false);
68 setcallback(WvStreamCallback(this, &FunFS::line_mode_execute), NULL);
70 log("FunFS Initialized!\n");
73 FunFS::~FunFS()
75 terminate_continue_select();
77 log("FunFS Destructor!\n");
80 bool FunFS::isok() const
82 if (ok && cloned && mycloned->isconnected() && !cloned->isok())
84 log(WvLog::Error, "Connection to %s lost!\n", *mycloned->src());
85 ok = false;
87 else if (ok && cloned && !cloned->isok())
89 log(WvLog::Error, "Connecting to %s: %s\n", *mycloned->src(),
90 cloned->errstr());
91 ok = false;
93 return ok;
96 size_t FunFS::write(WvStream *job, WvBuf &inbuf)
98 if (jobmap.exists(jobid))
100 log(WvLog::Error, "Expiring job #%s\n", (int)jobid);
101 jobmap.remove(jobid);
104 log("Adding a new job #%s\n", (int)jobid);
106 jobmap.add(jobid, job);
108 uint16 temp = jobid;
109 cloned->write(SWAP16(&temp), sizeof(temp));
111 if (!++jobid)
112 jobid++;
114 //fprintf(stderr, "writing %d bytes\n", inbuf.used());
115 size_t r = cloned->write(inbuf);
116 cloned->flush(0);
118 inbuf.zap();
120 return r;
123 void FunFS::line_mode_execute(WvStream &, void *)
125 WvString line = getline(2000);
127 if (!line)
129 log(WvLog::Error, "Connection to %s timed out.\n", *mycloned->src());
130 ok = false;
133 if (!strstr(line.cstr(), "FunFS"))
135 log(WvLog::Error, "%s is not a FunFS server.\n", *mycloned->src());
136 ok = false;
139 // Switch to data mode
140 mycloned->delay_output(true);
142 setcallback(WvStreamCallback(this, &FunFS::data_mode_execute), NULL);
145 void FunFS::data_mode_execute(WvStream &, void *)
147 if (xinbuf.used())
149 log(WvLog::Error, "Oh-oh! Somebody was slacking on reads!\n");
150 xinbuf.zap();
153 uint16 replyid = 0;
154 READ(replyid);
156 uint32 clength = 0;
157 READ(clength);
159 log("FunFS::execute: replyid = %s, clength = %s\n", replyid, clength);
161 size_t r = continue_read(-1, xinbuf, clength);
162 assert(r == clength);
164 if (replyid)
165 got_reply(replyid);
166 else
167 got_message();
170 void FunFS::got_reply(uint16 replyid)
172 if (jobmap.exists(replyid))
174 // Wake up the guy who's reply this is
175 jobmap[replyid]->alarm(0);
177 do {
178 continue_select(-1);
179 } while (!alarm_was_ticking);
181 jobmap.remove(replyid);
183 else
184 log(WvLog::Error, "Unknown jobid %s!\n", (int)replyid);
187 void FunFS::got_message()
189 reply_ready = true;
190 int jobtype = xinbuf.getch();
191 WvString path = xinbuf.getstr(xinbuf.strchr('\0'));
193 log(WvLog::Debug3, "<BOB> got a message of type [%s], path = '%s'!\n",
194 jobtype, path);
196 switch (jobtype)
198 case JT_GETATTR:
199 messagecb(MT_GETATTR, path);
200 break;
202 case JT_READLINK:
203 messagecb(MT_READLINK, path);
204 break;
206 default:
207 log(WvLog::Error, "<BOB> unknown message type\n");
210 if (xinbuf.used())
212 log(WvLog::Warning, "<BOB> Discarding %s bytes.\n", xinbuf.used());
213 xinbuf.zap();
216 reply_ready = false;
219 /******************************************************************/
221 int FunFS::fs_getattr(CONTEXT, PATH, struct fuse_attr *attr)
223 if (!reply_ready)
225 xoutbuf.putch(JT_GETATTR);
226 PUTPATH(path);
228 write(context, xoutbuf);
230 CONTINUE_SELECT();
231 MAYBECHECKERROR();
234 decode_fuse_attr(xinbuf, attr);
236 RETURN(0);
239 int FunFS::fs_getdir(CONTEXT, PATH, WvFuseDirCb &cb)
241 xoutbuf.putch(JT_GETDIR);
242 PUTPATH(path);
244 write(context, xoutbuf);
246 CONTINUE_SELECT();
248 MAYBECHECKERROR();
250 fuse_dirent fde;
252 while (xinbuf.used())
254 decode_fuse_dirent(xinbuf, &fde);
255 cb(&fde);
258 RETURN(0);
261 int FunFS::fs_open(CONTEXT, PATH, int flags)
263 xoutbuf.putch(JT_OPEN);
264 PUTPATH(path);
265 xoutbuf.put(SWAP32(&flags), 4);
267 write(context, xoutbuf);
269 CONTINUE_SELECT();
270 MAYBECHECKERROR();
272 int fd;
273 BUFREAD(fd);
275 RETURN(fd);
278 int FunFS::fs_release(CONTEXT, FD)
280 // FIXME: this should not even wait for a responce
281 xoutbuf.putch(JT_RELEASE);
283 xoutbuf.put(SWAP32(&fd), 4);
285 write(context, xoutbuf);
287 CONTINUE_SELECT();
289 RETURN(0);
292 int FunFS::fs_read(CONTEXT, FD, char *chbuf, size_t size, off_t offset)
294 xoutbuf.putch(JT_READ);
296 xoutbuf.put(SWAP32(&fd), 4);
297 xoutbuf.put(SWAP32(&size), 4);
298 xoutbuf.put(SWAP32(&offset), 4);
300 write(context, xoutbuf);
302 CONTINUE_SELECT();
304 size_t r = xinbuf.used();
305 memcpy(chbuf, xinbuf.get(r), r);
307 RETURN(r);
310 int FunFS::fs_readlink(CONTEXT, PATH, char *chbuf, size_t size)
312 if (!reply_ready)
314 xoutbuf.putch(JT_READLINK);
315 PUTPATH(path);
317 write(context, xoutbuf);
318 CONTINUE_SELECT();
321 CHECKERROR();
323 strncpy(chbuf, xinbuf.getstr(), size);
325 RETURN(0);
328 int FunFS::fs_statfs(CONTEXT, struct fuse_kstatfs *fst)
330 log(WvLog::Debug4, "fs_statfs called\n");
332 xoutbuf.putch(JT_STATFS);
334 write(context, xoutbuf);
336 CONTINUE_SELECT();
337 MAYBECHECKERROR();
339 decode_fuse_kstatfs(xinbuf, fst);
341 RETURN(0);
344 int FunFS::fs_symlink(CONTEXT, PATH, WvStringParm to)
346 // TODO
347 log(WvLog::Error, "fs_symlink not implemented!\n");
350 int res = symlink(path, to);
351 if(res == -1)
352 return -errno;
355 return -ENOSYS;
358 int FunFS::fs_truncate(CONTEXT, FD, off_t size)
360 // TODO
361 log(WvLog::Error, "fs_truncate not implemented!\n");
364 int res = truncate(path, size);
365 if(res == -1)
366 return -errno;
369 return -ENOSYS;
372 int FunFS::fs_unlink(CONTEXT, PATH)
374 // TODO
375 log(WvLog::Error, "fs_unlink not implemented!\n");
378 int res = unlink(path);
379 if(res == -1)
380 return -errno;
383 return -ENOSYS;
386 int FunFS::fs_utime(CONTEXT, PATH, struct utimbuf *utbuf)
389 WvDynBuf buf;
390 buf.putch(JT_READLINK);
391 buf.put(path, path.len() + 1);
393 write(context, buf);
395 CONTINUE_SELECT();
397 uint32 actime = 0, modtime = 0;
399 READ(actime);
400 READ(modtime);
402 if (utbuf)
404 utbuf->actime = actime;
405 utbuf->modtime = modtime;
407 else
409 // TODO
410 fprintf(stderr, "Updating utime not implemented yet.\n");
414 return -ENOSYS;
417 int FunFS::fs_write(CONTEXT, FD, const char *buf,
418 size_t size, off_t offset)
420 // TODO
421 log(WvLog::Error, "fs_write not implemented!\n");
424 int fd;
425 int res;
427 fd = open(path, O_WRONLY);
428 if(fd == -1)
429 return -errno;
431 res = pwrite(fd, buf, size, offset);
432 if(res == -1)
433 res = -errno;
435 ::close(fd);
437 return res;
440 return -ENOSYS;
443 int FunFS::fs_chmod(CONTEXT, PATH, mode_t mode)
445 // TODO
446 log(WvLog::Error, "fs_chmod not implemented!\n");
449 int res;
451 res = chmod(path, mode);
452 if(res == -1)
453 return -errno;
456 return -ENOSYS;
459 int FunFS::fs_chown(CONTEXT, PATH, uid_t uid, gid_t gid)
461 // TODO
462 log(WvLog::Error, "fs_chown not implemented!\n");
465 int res;
467 res = lchown(path, uid, gid);
468 if(res == -1)
469 return -errno;
472 return -ENOSYS;
475 int FunFS::fs_rename(CONTEXT, PATH, WvStringParm to)
477 // TODO
478 log(WvLog::Error, "fs_rename not implemented!\n");
481 int res = rename(path, to);
483 if(res == -1)
484 return -errno;
487 return -ENOSYS;
490 int FunFS::fs_mkdir(CONTEXT, PATH, mode_t mode)
492 // TODO
493 log(WvLog::Error, "fs_mkdir not implemented!\n");
496 int res;
498 res = mkdir(path, mode);
499 if(res == -1)
500 return -errno;
503 return -ENOSYS;
506 int FunFS::fs_mknod(CONTEXT, PATH, mode_t mode, dev_t rdev)
508 // TODO
509 log(WvLog::Error, "fs_mknod not implemented!\n");
512 int res = mknod(path, mode, rdev);
513 if(res == -1)
514 return -errno;
517 return -ENOSYS;
520 int FunFS::fs_link(CONTEXT, PATH, WvStringParm to)
523 WvDynBuf buf;
524 buf.putch(JT_LINK);
525 buf.put(path, path.len() + 1);
526 buf.put(to, to.len() + 1);
528 write(context, buf);
530 CONTINUE_SELECT();
531 CHECKERROR();
533 //READCLENGTH("link");
535 // For now we should always get an error.
536 assert(0);
537 return 0;
540 return -ENOSYS;
543 int FunFS::fs_rmdir(CONTEXT, PATH)
545 // TODO
546 log(WvLog::Error, "fs_rmdir not implemented!\n");
549 int res = rmdir(path);
550 if(res == -1)
551 return -errno;
554 return -ENOSYS;