2 #include "funfscodecs.h"
3 #include "wvfshelpers.h"
6 #include <wvistreamlist.h>
15 WvString path = getline(-1); \
19 FunFSd::FunFSd(int port
, bool _forkok
)
20 : forkok(_forkok
), listener(WvIPPortAddr("0.0.0.0", port
)),
21 log("FunFSd", WvLog::Info
)
23 log("Listening on port %s.\n", port
);
25 listener
.setcallback(WvStreamCallback(this, &FunFSd::callback_incoming
), 0);
27 append(&listener
, false);
31 bool FunFSd::isok() const
35 log(WvLog::Error
, "%s.", listener
.errstr());
42 void FunFSd::callback_incoming(WvStream
&, void *)
44 WvFDStream
*s
= listener
.accept();
46 int pid
= forkok
? wvfork(s
->getfd()) : 0;
54 WvIStreamList::globallist
.append(new FunFSdCon(s
, forkok
), true);
58 log(WvLog::Error
, "Fork failed!\n");
63 FunFSdCon::FunFSdCon(WvStream
*s
, bool _quit_on_disconnect
)
64 : WvStreamClone(s
), quit_on_disconnect(_quit_on_disconnect
),
65 log(WvString("Client<%s>", *s
->src()), WvLog::Debug2
)
67 log(WvLog::Info
, "Incoming connection.\n");
68 uses_continue_select
= true;
70 s
->write("FunFS Server 0.0 ready\n");
72 setcallback(WvStreamCallback(this, &FunFSdCon::line_mode_execute
), NULL
);
76 FunFSdCon::~FunFSdCon()
80 log(WvLog::Info
, "Connection terminated.\n");
82 terminate_continue_select();
84 if (quit_on_disconnect
)
89 void FunFSdCon::line_mode_execute(WvStream
&, void *)
91 WvStream
*&mycloned
= (WvStream
*)cloned
;
93 // Switch to data mode
94 mycloned
->delay_output(true);
95 setcallback(WvStreamCallback(this, &FunFSdCon::data_mode_execute
), NULL
);
99 void FunFSdCon::data_mode_execute(WvStream
&, void *)
107 log(WvLog::Debug4
, "jobid = %s, jobtype = %s\n", (int)jobid
, (int)jobtype
);
114 // FIXME: parallelize replys
115 cloned
->write(SWAP16(&jobid
), sizeof(jobid
));
156 void FunFSdCon::flush_queued()
158 if (int c
= queue
.count())
159 log("<BOB> Flushing %s queued message(s).\n", c
);
161 WvList
<WvDynBuf
>::Iter
i(queue
);
163 for (i
.rewind(); i
.next(); )
165 cloned
->write(&jobid
, sizeof(jobid
));
172 size_t FunFSdCon::write(WvBuf
&inbuf
, size_t count
)
174 //fprintf(stderr, "wrote count %d\n", inbuf.used());
175 uint32 clength
= inbuf
.used();
177 cloned
->write(SWAP32(&clength
), sizeof(clength
));
178 size_t r
= cloned
->write(inbuf
);
187 void FunFSdCon::handle_getdir()
190 log("<GetDir> Read path: %s\n", path
);
195 DIR *dp
= opendir(path
);
200 xoutbuf
.put(SWAP16(&err
), sizeof(err
));
204 cim_mark_uptodate(path
, JT_GETDIR
);
207 while (dp
&& (de
= readdir(dp
)) != NULL
)
209 if (strcmp(de
->d_name
, ".") && strcmp(de
->d_name
, ".."))
211 WvString
fullpath("%s/%s", path
, de
->d_name
);
213 // Make sure we fill in the type field if libc didn't
214 if (de
->d_type
== DT_UNKNOWN
)
216 if (!lstat(fullpath
, &stbuf
))
218 de
->d_type
= IFTODT(stbuf
.st_mode
);
221 fprintf(stderr
, "Error stat'ing '%s': %s.\n",
222 WvString("%s/%s", path
, de
->d_name
).cstr(),
226 // Presend the information the client might be interested in
230 enqueue(JT_READLINK
, fullpath
);
232 enqueue(JT_GETATTR
, fullpath
);
235 fprintf(stderr
, "Still no type in getdir!\n");
239 encode_fuse_dirent(xoutbuf
, de
);
247 void FunFSdCon::enqueue(JobType type
, WvStringParm path
)
249 WvDynBuf
*mybuf
= new WvDynBuf();
255 bool success
= false;
260 success
= do_readlink(path
, *mybuf
);
263 success
= do_getattr(path
, *mybuf
);
271 queue
.append(mybuf
, true);
277 void FunFSdCon::handle_getattr()
280 log("<GetAttr> Read path: %s\n", path
);
282 do_getattr(path
, xoutbuf
);
288 bool FunFSdCon::do_getattr(WvStringParm path
, WvDynBuf
&myoutbuf
)
292 int res
= lstat(path
, &stbuf
);
297 myoutbuf
.put(SWAP16(&err
), sizeof(err
));
302 convert_stat(&stbuf
, &attr
);
303 encode_fuse_attr(myoutbuf
, &attr
);
304 cim_mark_uptodate(path
, JT_GETATTR
);
311 void FunFSdCon::handle_readlink()
314 log("<ReadLink> Read path: %s\n", path
);
316 do_readlink(path
, xoutbuf
);
321 bool FunFSdCon::do_readlink(WvStringParm path
, WvDynBuf
&myoutbuf
)
325 int size
= readlink(path
, link
, PATH_MAX
);
327 uint16 err
= (size
>= 0 ? 0 : errno
);
328 myoutbuf
.put(SWAP16(&err
), sizeof(err
));
332 cim_mark_uptodate(path
, JT_READLINK
);
333 myoutbuf
.put(link
, size
);
334 myoutbuf
.putch('\0');
340 void FunFSdCon::handle_read()
350 //fprintf(stderr, "fd = %d, size = %lu, offset = %lu\n", fd, size, offset);
353 int remaining
= size
;
356 char *tmpbuf
= new char[size
];
358 for (char *where
= tmpbuf
; remaining
> 0; where
+= res
,
359 remaining
-= res
, offset
+= res
)
361 res
= ::pread(fd
, where
, remaining
, offset
);
366 // Zero indicates end of file
372 fprintf(stderr
, "Error on read: %s\n", strerror(errno
));
374 if (size
- remaining
)
375 xoutbuf
.put(tmpbuf
, size
- remaining
);
377 //fprintf(stderr, "buf.used(): %d\n", buf.used());
384 void FunFSdCon::handle_statfs()
388 // FIXME: this should use filesystem root
389 int res
= statfs("/",&st
);
394 xoutbuf
.put(SWAP16(&err
), sizeof(err
));
399 convert_statfs(&st
, &fst
);
400 encode_fuse_kstatfs(xoutbuf
, &fst
);
406 void FunFSdCon::handle_open()
413 int fd
= ::open(path
, flags
);
417 cim_do_open(path
, fd
);
418 xoutbuf
.put(SWAP32(&fd
), sizeof(fd
));
423 xoutbuf
.put(SWAP16(&err
), sizeof(err
));
429 void FunFSdCon::handle_release()
441 void FunFSdCon::handle_link()
443 WvString from = getline(-1, '\0');
445 WvString to = getline(-1, '\0');
448 int res = link(from, to);
457 void FunFSdCon::handle_utime()
459 WvString path = getline(-1, '\0');
464 log("<Utime>Read path: %s\n", path);
466 struct utimbuf utbuf;
468 int res = utime(path, &utbuf);
474 xoutbuf.put(SWAP32(&utbuf.actime), 32);
475 xoutbuf.put(SWAP32(&utbuf.modtime), 32);
483 void FunFSdCon::file_changed(WvStringParm path
)
485 log(WvLog::Debug4
, "%s changed!\n");
489 void FunFSdCon::file_deleted(WvStringParm path
)
491 log(WvLog::Debug4
, "%s deleted!\n");
495 void FunFSdCon::file_created(WvStringParm path
)
497 log(WvLog::Debug4
, "%s created!\n");