/[fuse_dbi]/fuse/trunk/lufis/lufis.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /fuse/trunk/lufis/lufis.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5 - (show annotations)
Wed Aug 4 11:40:49 2004 UTC (19 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 18555 byte(s)
copy CVS to trunk

1 #define _GNU_SOURCE
2
3 #include <lufs/fs.h>
4 #include <lufs/proto.h>
5 #include <fuse.h>
6 #include "list.h"
7 #include "dircache.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <dlfcn.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <sys/vfs.h>
16
17 /* statfs extension for captivefs */
18 struct lufs_sbattr_ { /* struct statfs64 */
19 unsigned long long sb_bytes;
20 unsigned long long sb_bytes_free;
21 unsigned long long sb_bytes_available;
22 unsigned long long sb_files;
23 unsigned long long sb_ffree;
24 };
25
26 struct fs_operations {
27 void *(*init)(struct list_head*, struct dir_cache*, struct credentials*, void**);
28 void (*free)(void*);
29 int (*mount)(void*);
30 void (*umount)(void*);
31 int (*readdir)(void*, char*, struct directory*);
32 int (*stat)(void*, char*, struct lufs_fattr*);
33 int (*mkdir)(void*, char*, int);
34 int (*rmdir)(void*, char*);
35 int (*create)(void*, char*, int);
36 int (*unlink)(void*, char*);
37 int (*rename)(void*, char*, char*);
38 int (*open)(void*, char*, unsigned);
39 int (*release)(void*, char*);
40 int (*read)(void*, char*, long long, unsigned long, char*);
41 int (*write)(void*, char*, long long, unsigned long, char*);
42 int (*readlink)(void*, char*, char*, int);
43 int (*link)(void*, char*, char*);
44 int (*symlink)(void*, char*, char*);
45 int (*setattr)(void*, char*, struct lufs_fattr*);
46 int (*statfs)(void*, struct lufs_sbattr_*);
47 };
48
49 static struct fs_operations lu_fops;
50 static void *lu_dlhandle;
51 static struct list_head lu_cfg;
52 static void *lu_global_ctx;
53 static struct credentials lu_cred;
54 static void *lu_context;
55 static struct dir_cache *lu_cache;
56
57 #define BUF_SIZE 1024
58 #define PASSWD "/etc/passwd"
59 #define GROUP "/etc/group"
60
61 int lu_check_to(int rd_fd, int wr_fd, int time_out){
62 fd_set rd, wr;
63 int res, maxfd = 0;
64 struct timeval tv;
65
66 FD_ZERO(&rd);
67 FD_ZERO(&wr);
68
69 if(rd_fd){
70 FD_SET(rd_fd, &rd);
71 maxfd = rd_fd > maxfd ? rd_fd : maxfd;
72 }
73
74 if(wr_fd){
75 FD_SET(wr_fd, &wr);
76 maxfd = wr_fd > maxfd ? wr_fd : maxfd;
77 }
78
79 tv.tv_sec = time_out;
80 tv.tv_usec = 0;
81
82 do{
83 res = select(maxfd + 1, &rd, &wr, NULL, &tv);
84
85 }while((res < 0) && (errno == EINTR));
86
87 if(res > 0)
88 return 0;
89
90 if(res < 0){
91 WARN("select call failed: %s", strerror(errno));
92 return -errno;
93 }
94
95 WARN("operation timed out!");
96
97 return -ETIMEDOUT;
98 }
99
100 int lu_atomic_read(int fd, char *buf, int len, int time_out){
101 int res, offset = 0;
102
103 do{
104 if((time_out) && ((res = lu_check_to(fd, 0, time_out)) < 0))
105 return res;
106
107 do{
108 res = read(fd, buf + offset, len - offset);
109 }while((res < 0) && (errno == EINTR));
110
111 if(res <= 0){
112 WARN("read call failed: %s", strerror(errno));
113 return (res < 0) ? -errno : (offset > 0 ? offset : -EPIPE);
114 }
115
116 offset += res;
117
118 }while(offset < len);
119
120 return offset;
121 }
122
123 int lu_atomic_write(int fd, char *buf, int len, int time_out){
124 int res, offset = 0;
125
126 do{
127 if((time_out) && ((res = lu_check_to(0, fd, time_out)) < 0))
128 return res;
129
130 do{
131 res = write(fd, buf + offset, len - offset);
132 }while((res < 0) && (errno == EINTR));
133
134 if(res <= 0){
135 WARN("write call failed: %s", strerror(errno));
136 return (res < 0) ? -errno : (offset > 0 ? offset : -EPIPE);
137 }
138
139 offset += res;
140
141 }while(offset < len);
142
143 return offset;
144 }
145
146 static int get_filesystem(const char *fs)
147 {
148 char *buf;
149 void *dlhandle;
150
151 if(!(buf = (char*)malloc(strlen(fs) + 32)))
152 return -1;
153
154 sprintf(buf, "liblufs-%s.so", fs);
155 if(!(dlhandle = dlopen(buf, RTLD_LAZY))){
156 ERROR(dlerror());
157 goto fail;
158 }
159
160 sprintf(buf, "%s_init", fs);
161 if(!(lu_fops.init = (void*(*)(struct list_head*, struct dir_cache*, struct credentials*, void**))dlsym(dlhandle, buf))){
162 ERROR(dlerror());
163 goto fail_fops;
164 }
165
166 sprintf(buf, "%s_free", fs);
167 if(!(lu_fops.free = (void(*)(void*))dlsym(dlhandle, buf))){
168 ERROR(dlerror());
169 goto fail_fops;
170 }
171
172 sprintf(buf, "%s_mount", fs);
173 if(!(lu_fops.mount = (int(*)(void*))dlsym(dlhandle, buf))){
174 ERROR(dlerror());
175 goto fail_fops;
176 }
177
178 sprintf(buf, "%s_umount", fs);
179 if(!(lu_fops.umount = (void(*)(void*))dlsym(dlhandle, buf)))
180 ERROR(dlerror());
181
182 sprintf(buf, "%s_readdir", fs);
183 if(!(lu_fops.readdir = (int(*)(void*, char*, struct directory*))dlsym(dlhandle, buf)))
184 ERROR(dlerror());
185
186 sprintf(buf, "%s_stat", fs);
187 if(!(lu_fops.stat = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf)))
188 ERROR(dlerror());
189
190 sprintf(buf, "%s_mkdir", fs);
191 if(!(lu_fops.mkdir = (int(*)(void*, char*, int))dlsym(dlhandle, buf)))
192 ERROR(dlerror());
193
194 sprintf(buf, "%s_rmdir", fs);
195 if(!(lu_fops.rmdir = (int(*)(void*, char*))dlsym(dlhandle, buf)))
196 ERROR(dlerror());
197
198 sprintf(buf, "%s_create", fs);
199 if(!(lu_fops.create = (int(*)(void*, char*, int))dlsym(dlhandle, buf)))
200 ERROR(dlerror());
201
202 sprintf(buf, "%s_unlink", fs);
203 if(!(lu_fops.unlink = (int(*)(void*, char*))dlsym(dlhandle, buf)))
204 ERROR(dlerror());
205
206 sprintf(buf, "%s_rename", fs);
207 if(!(lu_fops.rename = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
208 ERROR(dlerror());
209
210 sprintf(buf, "%s_open", fs);
211 if(!(lu_fops.open = (int(*)(void*, char*, unsigned))dlsym(dlhandle, buf)))
212 ERROR(dlerror());
213
214 sprintf(buf, "%s_release", fs);
215 if(!(lu_fops.release = (int(*)(void*, char*))dlsym(dlhandle, buf)))
216 ERROR(dlerror());
217
218 sprintf(buf, "%s_read", fs);
219 if(!(lu_fops.read = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf)))
220 ERROR(dlerror());
221
222 sprintf(buf, "%s_write", fs);
223 if(!(lu_fops.write = (int(*)(void*, char*, long long, unsigned long, char*))dlsym(dlhandle, buf)))
224 ERROR(dlerror());
225
226 sprintf(buf, "%s_readlink", fs);
227 if(!(lu_fops.readlink = (int(*)(void*, char*, char*, int))dlsym(dlhandle, buf)))
228 ERROR(dlerror());
229
230 sprintf(buf, "%s_link", fs);
231 if(!(lu_fops.link = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
232 ERROR(dlerror());
233
234 sprintf(buf, "%s_symlink", fs);
235 if(!(lu_fops.symlink = (int(*)(void*, char*, char*))dlsym(dlhandle, buf)))
236 ERROR(dlerror());
237
238 sprintf(buf, "%s_setattr", fs);
239 if(!(lu_fops.setattr = (int(*)(void*, char*, struct lufs_fattr*))dlsym(dlhandle, buf)))
240 ERROR(dlerror());
241 sprintf(buf, "%s_statfs", fs);
242 lu_fops.statfs = (int(*)(void*, struct lufs_sbattr_*))dlsym(dlhandle, buf);
243
244 lu_dlhandle = dlhandle;
245 free(buf);
246 return 0;
247
248 fail_fops:
249 dlclose(dlhandle);
250 fail:
251 free(buf);
252 return -1;
253 }
254
255 static int lu_getattr_native(const char *path, struct lufs_fattr *fattr)
256 {
257 if(!lu_fops.stat)
258 return -ENOSYS;
259
260 memset(fattr, 0, sizeof(struct lufs_fattr));
261 if(lu_cache_lookup_file(lu_cache, (char *) path, fattr, NULL, 0) < 0) {
262 if(lu_fops.stat(lu_context, (char *) path, fattr) < 0)
263 return -ENOENT;
264 }
265 return 0;
266 }
267
268 static int lu_getattr(const char *path, struct stat *stbuf)
269 {
270 struct lufs_fattr fattr;
271 int res;
272
273 res = lu_getattr_native(path, &fattr);
274 if(res < 0)
275 return res;
276
277 stbuf->st_mode = fattr.f_mode;
278 stbuf->st_nlink = fattr.f_nlink;
279 stbuf->st_uid = fattr.f_uid;
280 stbuf->st_gid = fattr.f_gid;
281 stbuf->st_size = fattr.f_size;
282 stbuf->st_atime = fattr.f_atime;
283 stbuf->st_mtime = fattr.f_mtime;
284 stbuf->st_ctime = fattr.f_ctime;
285 stbuf->st_blksize = fattr.f_blksize;
286 stbuf->st_blocks = fattr.f_blocks;
287
288 return 0;
289 }
290
291 static int lu_readlink(const char *path, char *buf, size_t size)
292 {
293 int len;
294 struct lufs_fattr fattr;
295
296 if(!lu_fops.readlink)
297 return -ENOSYS;
298
299 if(lu_cache_lookup_file(lu_cache, (char *) path, &fattr, buf, size) < 0 ||
300 strcmp(buf, "") == 0) {
301 if((len = lu_fops.readlink(lu_context, (char *) path, buf, size)) < 0)
302 return -EPERM;
303
304 /* FUSE leaves one extra char free at the end */
305 buf[len] = '\0';
306 }
307
308 return 0;
309 }
310
311 static int lu_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler)
312 {
313 struct directory *dir;
314
315 if(!lu_fops.readdir)
316 return -ENOSYS;
317
318 if(lu_cache_readdir(lu_cache, (char *) path, h, filler) < 0){
319 if(!(dir = lu_cache_mkdir((char *) path)))
320 return -1;
321
322 if(lu_fops.readdir(lu_context, (char *) path, dir) < 0){
323 lu_cache_killdir(dir);
324 return -1;
325 }
326 lu_cache_add_dir(lu_cache, dir);
327
328 if(lu_cache_readdir(lu_cache, (char *) path, h, filler) < 0) {
329 return -EPERM;
330 }
331 }
332 return 0;
333 }
334
335 static int lu_mknod(const char *path, mode_t mode, dev_t rdev)
336 {
337 (void) rdev;
338 if(!S_ISREG(mode) || !lu_fops.create)
339 return -ENOSYS;
340
341 if(lu_fops.create(lu_context, (char *) path, mode) < 0)
342 return -EPERM;
343
344 lu_cache_invalidate(lu_cache, (char *) path);
345 return 0;
346 }
347
348 static int lu_mkdir(const char *path, mode_t mode)
349 {
350 if(!lu_fops.mkdir)
351 return -ENOSYS;
352
353 if(lu_fops.mkdir(lu_context, (char *) path, mode) < 0)
354 return -EPERM;
355
356 lu_cache_invalidate(lu_cache, (char *) path);
357 return 0;
358 }
359
360 static int lu_unlink(const char *path)
361 {
362 if(!lu_fops.unlink)
363 return -ENOSYS;
364
365 if(lu_fops.unlink(lu_context, (char *) path) < 0)
366 return -EPERM;
367
368 lu_cache_invalidate(lu_cache, (char *) path);
369 return 0;
370 }
371
372 static int lu_rmdir(const char *path)
373 {
374 if(!lu_fops.rmdir)
375 return -ENOSYS;
376
377 if(lu_fops.rmdir(lu_context, (char *) path) < 0)
378 return -EPERM;
379
380 lu_cache_invalidate(lu_cache, (char *) path);
381 return 0;
382 }
383
384 static int lu_symlink(const char *from, const char *to)
385 {
386 if(!lu_fops.symlink)
387 return -ENOSYS;
388
389 if(lu_fops.symlink(lu_context, (char *) from, (char *) to) < 0)
390 return -EPERM;
391
392 lu_cache_invalidate(lu_cache, (char *) to);
393 return 0;
394 }
395
396 static int lu_rename(const char *from, const char *to)
397 {
398 if(!lu_fops.rename)
399 return -ENOSYS;
400
401 if(lu_fops.rename(lu_context, (char *) from, (char *) to) < 0)
402 return -EPERM;
403
404 lu_cache_invalidate(lu_cache, (char *) from);
405 lu_cache_invalidate(lu_cache, (char *) to);
406 return 0;
407 }
408
409 static int lu_link(const char *from, const char *to)
410 {
411 if(!lu_fops.link)
412 return -ENOSYS;
413
414 if(lu_fops.link(lu_context, (char *) from, (char *) to) < 0)
415 return -EPERM;
416
417 lu_cache_invalidate(lu_cache, (char *) from);
418 lu_cache_invalidate(lu_cache, (char *) to);
419 return 0;
420 }
421
422 static int lu_chmod(const char *path, mode_t mode)
423 {
424 int res;
425 struct lufs_fattr fattr;
426
427 if(!lu_fops.setattr)
428 return -ENOSYS;
429
430 res = lu_getattr_native(path, &fattr);
431 if(res < 0)
432 return res;
433
434 fattr.f_mode = mode;
435 if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0)
436 return -EPERM;
437
438 lu_cache_invalidate(lu_cache, (char *) path);
439 return 0;
440 }
441
442 static int lu_chown(const char *path, uid_t uid, gid_t gid)
443 {
444 int res;
445 struct lufs_fattr fattr;
446
447 if(!lu_fops.setattr)
448 return -ENOSYS;
449
450 res = lu_getattr_native(path, &fattr);
451 if(res < 0)
452 return res;
453
454 if(uid != (uid_t) -1)
455 fattr.f_uid = uid;
456 if(gid != (gid_t) -1)
457 fattr.f_gid = gid;
458 if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0)
459 return -EPERM;
460
461 lu_cache_invalidate(lu_cache, (char *) path);
462 return 0;
463
464 }
465
466 static int lu_truncate(const char *path, off_t size)
467 {
468 int res;
469 struct lufs_fattr fattr;
470
471 if(!lu_fops.setattr)
472 return -ENOSYS;
473
474 res = lu_getattr_native(path, &fattr);
475 if(res < 0)
476 return res;
477
478 fattr.f_size = size;
479 if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0)
480 return -EPERM;
481
482 lu_cache_invalidate(lu_cache, (char *) path);
483 return 0;
484 }
485
486 static int lu_utime(const char *path, struct utimbuf *buf)
487 {
488 int res;
489 struct lufs_fattr fattr;
490
491 if(!lu_fops.setattr)
492 return -ENOSYS;
493
494 res = lu_getattr_native(path, &fattr);
495 if(res < 0)
496 return res;
497
498 fattr.f_atime = buf->actime;
499 fattr.f_mtime = buf->modtime;
500 if(lu_fops.setattr(lu_context, (char *) path, &fattr) < 0)
501 return -EPERM;
502
503 lu_cache_invalidate(lu_cache, (char *) path);
504 return 0;
505 }
506
507
508 static int lu_open(const char *path, int flags)
509 {
510 if(!lu_fops.open)
511 return -ENOSYS;
512
513 if(lu_fops.open(lu_context, (char *) path, flags & O_ACCMODE) < 0)
514 return -EPERM;
515
516 return 0;
517 }
518
519 static int lu_read(const char *path, char *buf, size_t size, off_t offset)
520 {
521 int res;
522 if(!lu_fops.read)
523 return -ENOSYS;
524
525 if((res = lu_fops.read(lu_context, (char *) path, offset, size, buf)) < 0)
526 return -EPERM;
527
528 return res;
529 }
530
531 static int lu_write(const char *path, const char *buf, size_t size,
532 off_t offset)
533 {
534 if(!lu_fops.write)
535 return -ENOSYS;
536
537 if(lu_fops.write(lu_context, (char *) path, offset, size, (char *) buf) < 0)
538 return -EPERM;
539
540 return size;
541 }
542
543 static int lu_release(const char *path, int flags)
544 {
545 (void) flags;
546 if(!lu_fops.release)
547 return -ENOSYS;
548
549 if(lu_fops.release(lu_context, (char *) path) < 0)
550 return -EPERM;
551
552 return 0;
553 }
554
555 #if FUSE_MAJOR_VERSION < 2
556 static int lu_statfs(struct fuse_statfs *stbuf)
557 #else
558 static int lu_statfs(const char *path, struct statfs *stbuf)
559 #endif
560 {
561 struct lufs_sbattr_ sbattr;
562
563 memset(&sbattr, 0, sizeof(sbattr));
564 if(lu_fops.statfs) {
565 if(lu_fops.statfs(lu_context, &sbattr) < 0)
566 return -EPERM;
567 }
568
569 #if FUSE_MAJOR_VERSION < 2
570 stbuf->blocks = sbattr.sb_bytes / 512;
571 stbuf->blocks_free = sbattr.sb_bytes_available / 512;
572 stbuf->files = sbattr.sb_files;
573 stbuf->files_free = sbattr.sb_ffree;
574 stbuf->namelen = 255;
575 #else
576 (void) path;
577 stbuf->f_bsize = 512;
578 stbuf->f_blocks = sbattr.sb_bytes / 512;
579 stbuf->f_bfree = sbattr.sb_bytes_free / 512;
580 stbuf->f_bavail = sbattr.sb_bytes_available / 512;
581 stbuf->f_files = sbattr.sb_files;
582 stbuf->f_ffree = sbattr.sb_ffree;
583 stbuf->f_namelen = 255;
584 #endif
585 return 0;
586 }
587
588 static int load_credentials(void)
589 {
590 static char buf[BUF_SIZE];
591 char srch_str[MAX_LEN + 4];
592 long int uid, gid;
593 int res, offset, chunk, readlen;
594 char *c;
595
596 TRACE("loading remote credentials for %s", lu_cred.user);
597
598 if((!lu_fops.open) || (!lu_fops.read) || (!lu_fops.release)){
599 WARN("unsupported operation");
600 return -1;;
601 }
602
603 lu_cred.uid = lu_cred.gid = -1;
604
605 if(lu_fops.open(lu_context, PASSWD, O_RDONLY) < 0){
606 TRACE("could not open %s", PASSWD);
607 return -1;
608 }
609
610 sprintf(srch_str, "\n%s:", lu_cred.user);
611 chunk = strlen(srch_str) + 64;
612 readlen = BUF_SIZE - chunk - 1;
613
614 memset(buf, 32, chunk);
615 offset = 0;
616
617 do{
618 res = lu_fops.read(lu_context, PASSWD, offset, readlen, (buf + chunk));
619 if(res > 0){
620 *(buf + chunk + res) = 0;
621
622 if((c = strstr(buf, srch_str))){
623 TRACE("username found!");
624 if(!(c = strchr(c + strlen(srch_str), ':'))){
625 TRACE("separator not found!");
626 }else{
627 if(sscanf(c , ":%li:%li:", &uid, &gid) != 2){
628 TRACE("uid/gid not found!");
629 }else{
630 TRACE("uid: %li, gid: %li", uid, gid);
631
632 lu_cred.uid = uid;
633 lu_cred.gid = gid;
634
635 break;
636 }
637 }
638 }
639
640 memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk);
641 offset += res;
642 }
643 }while(res == readlen);
644
645 lu_fops.release(lu_context, PASSWD);
646
647 if(res <= 0){
648 TRACE("read failed");
649 return -1;
650 }
651
652
653 if(lu_fops.open(lu_context, GROUP, O_RDONLY) < 0){
654 TRACE("could not open %s", GROUP);
655 return -1;
656 }
657
658 sprintf(srch_str, ":%li:", (long)lu_cred.gid);
659 chunk = strlen(srch_str) + 64;
660 readlen = BUF_SIZE - chunk - 1;
661
662 memset(buf, 32, chunk);
663 offset = 0;
664
665 do{
666 res = lu_fops.read(lu_context, GROUP, offset, readlen, (buf + chunk));
667 if(res > 0){
668 *(buf + chunk + res) = 0;
669
670 if((c = strstr(buf, srch_str))){
671 TRACE("group found!");
672 if(!(c = (char*)memrchr(buf, '\n', (c - buf)))){
673 TRACE("separator not found!");
674 }else{
675 *(strchr(c, ':')) = 0;
676 if(strlen(c + 1) >= MAX_LEN){
677 TRACE("groupname too long");
678 }else{
679 strcpy(lu_cred.group, c + 1);
680 TRACE("group: %s", lu_cred.group);
681 break;
682 }
683 }
684 }
685
686 memcpy(buf, buf + BUF_SIZE - chunk - 1, chunk);
687 offset += res;
688 }
689 }while(res == readlen);
690
691 lu_fops.release(lu_context, GROUP);
692
693 if(res <= 0){
694 TRACE("read failed");
695 return -1;
696 }
697
698 return 0;
699 }
700
701 static int lufis_init(int *argcp, char **argvp[])
702 {
703 int argc = *argcp;
704 char **argv = *argvp;
705 int res;
706 char *opts;
707 const char *fs_name;
708
709 if(argc < 2) {
710 fprintf(stderr, "usage: %s opts\n", argv[0]);
711 return -1;
712 }
713
714 INIT_LIST_HEAD(&lu_cfg);
715 opts = argv[1];
716 if(lu_opt_parse(&lu_cfg, "MOUNT", opts) < 0){
717 ERROR("could not parse options!");
718 return -1;
719 }
720
721 lu_opt_loadcfg(&lu_cfg, "/etc/lufsd.conf");
722
723 (*argcp)--;
724 (*argvp)++;
725 argv[1] = argv[0];
726
727
728 lu_cache = lu_cache_create(&lu_cfg);
729 if(!lu_cache)
730 return -1;
731
732 if(!(fs_name = lu_opt_getchar(&lu_cfg, "MOUNT", "fs"))){
733 ERROR("you need to specify a file system!");
734 return -1;
735 }
736
737 res = get_filesystem(fs_name);
738 if(res == -1)
739 return -1;
740
741 if(!(lu_context = lu_fops.init(&lu_cfg, lu_cache, &lu_cred, &lu_global_ctx))) {
742 ERROR("could not initialize file system!");
743 return -1;
744 }
745
746 res = lu_fops.mount(lu_context);
747 if(res) {
748 if(load_credentials() < 0)
749 TRACE("could not load credentials.");
750 else
751 TRACE("credentials loaded.");
752 } else {
753 WARN("fs mount failed...");
754 }
755
756 return 0;
757 }
758
759 static void lufis_cleanup(void)
760 {
761 if(lu_fops.umount)
762 lu_fops.umount(lu_context);
763 lu_fops.free(lu_context);
764 }
765
766 static struct fuse_operations lu_oper = {
767 .getattr = lu_getattr,
768 .readlink = lu_readlink,
769 .getdir = lu_getdir,
770 .mknod = lu_mknod,
771 .mkdir = lu_mkdir,
772 .symlink = lu_symlink,
773 .unlink = lu_unlink,
774 .rmdir = lu_rmdir,
775 .rename = lu_rename,
776 .link = lu_link,
777 .chmod = lu_chmod,
778 .chown = lu_chown,
779 .truncate = lu_truncate,
780 .utime = lu_utime,
781 .open = lu_open,
782 .read = lu_read,
783 .write = lu_write,
784 .release = lu_release,
785 .statfs = lu_statfs,
786 };
787
788 int main(int argc, char *argv[])
789 {
790 int res;
791
792 res = lufis_init(&argc, &argv);
793 if(res == -1)
794 exit(1);
795
796 fuse_main(argc, argv, &lu_oper);
797 lufis_cleanup();
798
799 return 0;
800 }

  ViewVC Help
Powered by ViewVC 1.1.26