56 |
int type); |
int type); |
57 |
|
|
58 |
|
|
59 |
|
/* Check whether to allow access to a node, testing the allow_root and |
60 |
|
* allow_other flag. This does not check whether default permissions |
61 |
|
* are okay to allow access. |
62 |
|
* |
63 |
|
* Return: 0 if access is to be granted, EPERM otherwise |
64 |
|
* |
65 |
|
* Sidenote: This function is mainly called from netfs_validate_stat which in |
66 |
|
* turn is called by any other of the netfs-operation-functions. This |
67 |
|
* is, we don't have to call this from all of the operation-functions |
68 |
|
* since netfs_validate_stat is called anyways! |
69 |
|
*/ |
70 |
|
static error_t |
71 |
|
test_allow_root_or_other (struct iouser *cred) |
72 |
|
{ |
73 |
|
FUNC_PROLOGUE("test_allow_root_or_other"); |
74 |
|
|
75 |
|
/* if allow_other is set, access is okay in any case */ |
76 |
|
if(libfuse_params.allow_other) |
77 |
|
FUNC_RETURN_FMT(0, "allow_other is set"); |
78 |
|
|
79 |
|
unsigned int i; |
80 |
|
uid_t proc_uid = getuid(); |
81 |
|
for(i = 0; i < cred->uids->num; i ++) |
82 |
|
{ |
83 |
|
DEBUG("test_allow", "testing for uid=%d\n", cred->uids->ids[i]); |
84 |
|
|
85 |
|
if(cred->uids->ids[i] == 0 && libfuse_params.allow_root) |
86 |
|
FUNC_RETURN_FMT(0, "allowing access for root"); |
87 |
|
|
88 |
|
if(cred->uids->ids[i] == proc_uid) |
89 |
|
FUNC_RETURN_FMT(0, "allowing access for owner"); |
90 |
|
} |
91 |
|
|
92 |
|
/* iouser is not the "filesystem-owner" and allow_other is not set, |
93 |
|
* or iouser is root but allow_root is not set either */ |
94 |
|
FUNC_EPILOGUE(EPERM); |
95 |
|
} |
96 |
|
|
97 |
|
|
98 |
|
|
99 |
/* Make sure that NP->nn_stat is filled with current information. CRED |
/* Make sure that NP->nn_stat is filled with current information. CRED |
100 |
identifies the user responsible for the operation. */ |
identifies the user responsible for the operation. |
101 |
|
|
102 |
|
If the user `CRED' is not allowed to perform any operation (considering |
103 |
|
the allow_root and allow_other flags), return EPERM. */ |
104 |
error_t |
error_t |
105 |
netfs_validate_stat (struct node *node, struct iouser *cred) |
netfs_validate_stat (struct node *node, struct iouser *cred) |
106 |
{ |
{ |
|
(void) cred; |
|
|
|
|
107 |
FUNC_PROLOGUE_NODE("netfs_validate_stat", node); |
FUNC_PROLOGUE_NODE("netfs_validate_stat", node); |
108 |
error_t err = EOPNOTSUPP; |
error_t err = EOPNOTSUPP; |
109 |
|
|
110 |
|
if(test_allow_root_or_other(cred)) |
111 |
|
FUNC_RETURN(EPERM); |
112 |
|
|
113 |
if(FUSE_OP_HAVE(getattr)) |
if(FUSE_OP_HAVE(getattr)) |
114 |
err = -FUSE_OP_CALL(getattr, node->nn->path, &node->nn_stat); |
err = -FUSE_OP_CALL(getattr, node->nn->path, &node->nn_stat); |
115 |
|
|
142 |
char *buf) |
char *buf) |
143 |
{ |
{ |
144 |
FUNC_PROLOGUE_NODE("netfs_attempt_readlink", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_readlink", node); |
145 |
error_t err = EOPNOTSUPP; |
error_t err; |
146 |
|
|
147 |
if((err = netfs_validate_stat(node, user)) |
if((err = netfs_validate_stat(node, user)) |
148 |
|| (err = fshelp_access(&node->nn_stat, S_IREAD, user))) |
|| (err = fshelp_access(&node->nn_stat, S_IREAD, user))) |
150 |
|
|
151 |
if(FUSE_OP_HAVE(readlink)) |
if(FUSE_OP_HAVE(readlink)) |
152 |
err = -FUSE_OP_CALL(readlink, node->nn->path, buf, INT_MAX); |
err = -FUSE_OP_CALL(readlink, node->nn->path, buf, INT_MAX); |
153 |
|
else |
154 |
|
err = EOPNOTSUPP; |
155 |
|
|
156 |
out: |
out: |
157 |
FUNC_EPILOGUE(err); |
FUNC_EPILOGUE(err); |
167 |
char *name, mode_t mode, struct node **node) |
char *name, mode_t mode, struct node **node) |
168 |
{ |
{ |
169 |
FUNC_PROLOGUE("netfs_attempt_create_file"); |
FUNC_PROLOGUE("netfs_attempt_create_file"); |
170 |
error_t err = EOPNOTSUPP; |
error_t err; |
171 |
char *path = NULL; |
char *path = NULL; |
172 |
|
|
|
if(! FUSE_OP_HAVE(mknod)) |
|
|
goto out; |
|
|
|
|
173 |
if((err = netfs_validate_stat(dir, user)) |
if((err = netfs_validate_stat(dir, user)) |
174 |
|| (err = fshelp_checkdirmod(&dir->nn_stat, NULL, user))) |
|| (err = fshelp_checkdirmod(&dir->nn_stat, NULL, user))) |
175 |
goto out; |
goto out; |
176 |
|
|
177 |
|
if(! FUSE_OP_HAVE(mknod)) |
178 |
|
{ |
179 |
|
err = EOPNOTSUPP; |
180 |
|
goto out; |
181 |
|
} |
182 |
|
|
183 |
if(! (path = malloc(strlen(dir->nn->path) + strlen(name) + 2))) |
if(! (path = malloc(strlen(dir->nn->path) + strlen(name) + 2))) |
184 |
{ |
{ |
185 |
err = ENOMEM; |
err = ENOMEM; |
245 |
uid_t uid, uid_t gid) |
uid_t uid, uid_t gid) |
246 |
{ |
{ |
247 |
FUNC_PROLOGUE_NODE("netfs_attempt_chown", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_chown", node); |
248 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
if(! FUSE_OP_HAVE(chown)) |
|
|
goto out; |
|
249 |
|
|
250 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
251 |
|| (err = fshelp_isowner(&node->nn_stat, cred))) |
|| (err = fshelp_isowner(&node->nn_stat, cred))) |
252 |
goto out; |
goto out; |
253 |
|
|
254 |
|
if(! FUSE_OP_HAVE(chown)) |
255 |
|
{ |
256 |
|
err = EOPNOTSUPP; |
257 |
|
goto out; |
258 |
|
} |
259 |
|
|
260 |
/* FIXME, make sure, that user CRED is not able to change permissions |
/* FIXME, make sure, that user CRED is not able to change permissions |
261 |
* to somebody who is not. That is, don't allow $unpriv_user to change |
* to somebody who is not. That is, don't allow $unpriv_user to change |
262 |
* owner to e.g. root. |
* owner to e.g. root. |
277 |
netfs_attempt_statfs (struct iouser *cred, struct node *node, |
netfs_attempt_statfs (struct iouser *cred, struct node *node, |
278 |
fsys_statfsbuf_t *st) |
fsys_statfsbuf_t *st) |
279 |
{ |
{ |
|
(void) cred; |
|
|
|
|
280 |
FUNC_PROLOGUE_NODE("netfs_attempt_statfs", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_statfs", node); |
281 |
error_t err = EOPNOTSUPP; |
error_t err; |
282 |
|
|
283 |
if(FUSE_OP_HAVE(statfs)) |
if(test_allow_root_or_other(cred)) |
284 |
|
err = EPERM; |
285 |
|
|
286 |
|
else if(FUSE_OP_HAVE(statfs)) |
287 |
err = -FUSE_OP_CALL(statfs, node->nn->path, st); |
err = -FUSE_OP_CALL(statfs, node->nn->path, st); |
288 |
|
|
289 |
|
else |
290 |
|
err = EOPNOTSUPP; |
291 |
|
|
292 |
FUNC_EPILOGUE(err); |
FUNC_EPILOGUE(err); |
293 |
} |
} |
294 |
|
|
300 |
char *name, mode_t mode) |
char *name, mode_t mode) |
301 |
{ |
{ |
302 |
FUNC_PROLOGUE("netfs_attempt_mkdir"); |
FUNC_PROLOGUE("netfs_attempt_mkdir"); |
303 |
error_t err = EOPNOTSUPP; |
error_t err; |
304 |
char *path = NULL; |
char *path = NULL; |
305 |
|
|
|
if(! FUSE_OP_HAVE(mkdir)) |
|
|
goto out; |
|
|
|
|
306 |
if((err = netfs_validate_stat(dir, user)) |
if((err = netfs_validate_stat(dir, user)) |
307 |
|| (err = fshelp_checkdirmod(&dir->nn_stat, NULL, user))) |
|| (err = fshelp_checkdirmod(&dir->nn_stat, NULL, user))) |
308 |
goto out; |
goto out; |
309 |
|
|
310 |
|
if(! FUSE_OP_HAVE(mkdir)) |
311 |
|
{ |
312 |
|
err = EOPNOTSUPP; |
313 |
|
goto out; |
314 |
|
} |
315 |
|
|
316 |
if(! (path = malloc(strlen(dir->nn->path) + strlen(name) + 2))) |
if(! (path = malloc(strlen(dir->nn->path) + strlen(name) + 2))) |
317 |
{ |
{ |
318 |
err = ENOMEM; |
err = ENOMEM; |
403 |
mode_t mode) |
mode_t mode) |
404 |
{ |
{ |
405 |
FUNC_PROLOGUE_NODE("netfs_attempt_chmod", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_chmod", node); |
406 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
if(! FUSE_OP_HAVE(chmod)) |
|
|
goto out; |
|
407 |
|
|
408 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
409 |
|| (err = fshelp_isowner(&node->nn_stat, cred))) |
|| (err = fshelp_isowner(&node->nn_stat, cred))) |
410 |
goto out; |
goto out; |
411 |
|
|
412 |
|
if(! FUSE_OP_HAVE(chmod)) |
413 |
|
{ |
414 |
|
err = EOPNOTSUPP; |
415 |
|
goto out; |
416 |
|
} |
417 |
|
|
418 |
err = -FUSE_OP_CALL(chmod, node->nn->path, mode); |
err = -FUSE_OP_CALL(chmod, node->nn->path, mode); |
419 |
node->nn->may_need_sync = 1; |
node->nn->may_need_sync = 1; |
420 |
|
|
430 |
mode_t mode, struct node **node) |
mode_t mode, struct node **node) |
431 |
{ |
{ |
432 |
FUNC_PROLOGUE("netfs_attempt_mkfile"); |
FUNC_PROLOGUE("netfs_attempt_mkfile"); |
433 |
error_t err = EOPNOTSUPP; |
error_t err; |
434 |
char name[20]; |
char name[20]; |
435 |
static int num = 0; |
static int num = 0; |
436 |
|
|
437 |
if(FUSE_OP_HAVE(mknod)) |
if(! (err = netfs_validate_stat(dir, user))) |
438 |
if(! (err = netfs_validate_stat(dir, user))) |
err = fshelp_checkdirmod(&dir->nn_stat, NULL, user); |
439 |
err = fshelp_checkdirmod(&dir->nn_stat, NULL, user); |
|
440 |
|
if(! err && ! FUSE_OP_HAVE(mknod)) |
441 |
|
err = EOPNOTSUPP; |
442 |
|
|
443 |
if(err) |
if(err) |
444 |
{ |
{ |
487 |
only after sync is completely finished. */ |
only after sync is completely finished. */ |
488 |
error_t netfs_attempt_syncfs (struct iouser *cred, int wait) |
error_t netfs_attempt_syncfs (struct iouser *cred, int wait) |
489 |
{ |
{ |
|
(void) cred; /* cannot use anything but translator's rights, |
|
|
* FIXME, maybe setuid/setgid? */ |
|
490 |
(void) wait; /* there's no such flag in libfuse */ |
(void) wait; /* there's no such flag in libfuse */ |
491 |
|
|
492 |
FUNC_PROLOGUE("netfs_attempt_syncfs"); |
FUNC_PROLOGUE("netfs_attempt_syncfs"); |
493 |
error_t err = fuse_sync_filesystem(); |
error_t err; |
494 |
|
|
495 |
|
if(test_allow_root_or_other(cred)) |
496 |
|
err = EPERM; |
497 |
|
else |
498 |
|
err = fuse_sync_filesystem(); |
499 |
|
|
500 |
FUNC_EPILOGUE(err); |
FUNC_EPILOGUE(err); |
501 |
} |
} |
510 |
(void) wait; /* there's no such flag in libfuse */ |
(void) wait; /* there's no such flag in libfuse */ |
511 |
|
|
512 |
FUNC_PROLOGUE_NODE("netfs_attempt_sync", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_sync", node); |
513 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
if(! FUSE_OP_HAVE(fsync)) |
|
|
goto out; |
|
514 |
|
|
515 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
516 |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
517 |
goto out; |
goto out; |
518 |
|
|
519 |
|
if(! FUSE_OP_HAVE(fsync)) |
520 |
|
{ |
521 |
|
err = EOPNOTSUPP; |
522 |
|
goto out; |
523 |
|
} |
524 |
|
|
525 |
if(fuse_ops) |
if(fuse_ops) |
526 |
err = -fuse_ops->fsync(node->nn->path, 0, &node->nn->info); |
err = -fuse_ops->fsync(node->nn->path, 0, &node->nn->info); |
527 |
else |
else |
543 |
char *name) |
char *name) |
544 |
{ |
{ |
545 |
FUNC_PROLOGUE("netfs_attempt_unlink"); |
FUNC_PROLOGUE("netfs_attempt_unlink"); |
546 |
error_t err = EOPNOTSUPP; |
error_t err; |
547 |
struct node *node = NULL; |
struct node *node = NULL; |
548 |
|
|
|
if(! FUSE_OP_HAVE(unlink)) |
|
|
goto out; |
|
|
|
|
549 |
err = netfs_attempt_lookup(user, dir, name, &node); |
err = netfs_attempt_lookup(user, dir, name, &node); |
550 |
assert(dir != node); |
assert(dir != node); |
551 |
mutex_lock(&dir->lock); /* re-lock directory, since netfs_attempt_lookup |
mutex_lock(&dir->lock); /* re-lock directory, since netfs_attempt_lookup |
561 |
|| (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user))) |
|| (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user))) |
562 |
goto out; |
goto out; |
563 |
|
|
564 |
err = -FUSE_OP_CALL(unlink, node->nn->path); |
if(FUSE_OP_HAVE(unlink)) |
565 |
|
err = -FUSE_OP_CALL(unlink, node->nn->path); |
566 |
|
else |
567 |
|
err = EOPNOTSUPP; |
568 |
|
|
569 |
/* TODO free associated netnode. really? |
/* TODO free associated netnode. really? |
570 |
* FIXME, make sure nn->may_need_sync is set */ |
* FIXME, make sure nn->may_need_sync is set */ |
583 |
loff_t size) |
loff_t size) |
584 |
{ |
{ |
585 |
FUNC_PROLOGUE_NODE("netfs_attempt_set_size", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_set_size", node); |
586 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
if(! FUSE_OP_HAVE(truncate)) |
|
|
goto out; |
|
587 |
|
|
588 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
589 |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
590 |
goto out; |
goto out; |
591 |
|
|
592 |
err = -FUSE_OP_CALL(truncate, node->nn->path, size); |
if(FUSE_OP_HAVE(truncate)) |
593 |
|
err = -FUSE_OP_CALL(truncate, node->nn->path, size); |
594 |
|
else |
595 |
|
err = EOPNOTSUPP; |
596 |
|
|
597 |
out: |
out: |
598 |
FUNC_EPILOGUE(err); |
FUNC_EPILOGUE(err); |
606 |
mode_t type, dev_t indexes) |
mode_t type, dev_t indexes) |
607 |
{ |
{ |
608 |
FUNC_PROLOGUE_NODE("netfs_attempt_mkdev", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_mkdev", node); |
609 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
if(! FUSE_OP_HAVE(mknod)) |
|
|
goto out; |
|
|
|
|
|
/* we need to unlink the existing node, therefore, if unlink is not |
|
|
* available, we cannot turn *node into a device. |
|
|
*/ |
|
|
if(! FUSE_OP_HAVE(unlink)) |
|
|
goto out; |
|
610 |
|
|
611 |
/* check permissions |
/* check permissions |
612 |
* XXX, shall we check permissions of the parent directory as well, |
* XXX, shall we check permissions of the parent directory as well, |
613 |
* since we're going to unlink files? |
* since we're going to unlink files? |
614 |
*/ |
*/ |
|
|
|
615 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
616 |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
617 |
goto out; |
goto out; |
618 |
|
|
619 |
|
/* check whether the operations are available at all */ |
620 |
|
if(! FUSE_OP_HAVE(mknod)) |
621 |
|
{ |
622 |
|
err = EOPNOTSUPP; |
623 |
|
goto out; |
624 |
|
} |
625 |
|
|
626 |
|
/* we need to unlink the existing node, therefore, if unlink is not |
627 |
|
* available, we cannot turn *node into a device. |
628 |
|
*/ |
629 |
|
if(! FUSE_OP_HAVE(unlink)) |
630 |
|
{ |
631 |
|
err = EOPNOTSUPP; |
632 |
|
goto out; |
633 |
|
} |
634 |
|
|
635 |
/* unlink the already existing node, to be able to create the (new) |
/* unlink the already existing node, to be able to create the (new) |
636 |
* device file |
* device file |
637 |
*/ |
*/ |
773 |
{ |
{ |
774 |
FUNC_PROLOGUE_FMT("netfs_attempt_link", "link=%s/%s, to=%s", |
FUNC_PROLOGUE_FMT("netfs_attempt_link", "link=%s/%s, to=%s", |
775 |
dir->nn->path, name, file->nn->path); |
dir->nn->path, name, file->nn->path); |
776 |
error_t err = EOPNOTSUPP; |
error_t err; |
777 |
struct node *node = NULL; |
struct node *node = NULL; |
778 |
|
|
|
if(! FUSE_OP_HAVE(link)) |
|
|
goto out_nounlock; |
|
|
|
|
779 |
mutex_lock(&dir->lock); |
mutex_lock(&dir->lock); |
780 |
|
|
781 |
if((err = netfs_attempt_lookup(user, dir, name, &node))) |
if((err = netfs_attempt_lookup(user, dir, name, &node))) |
788 |
|| (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user))) |
|| (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user))) |
789 |
goto out; |
goto out; |
790 |
|
|
791 |
|
if(! FUSE_OP_HAVE(link)) { |
792 |
|
err = EOPNOTSUPP; |
793 |
|
goto out; |
794 |
|
} |
795 |
|
|
796 |
if(! excl && FUSE_OP_HAVE(unlink)) |
if(! excl && FUSE_OP_HAVE(unlink)) |
797 |
/* EXCL is not set, therefore we may remove the target, i.e. call |
/* EXCL is not set, therefore we may remove the target, i.e. call |
798 |
* unlink on it. Ignoring return value, as it's mostly not interesting, |
* unlink on it. Ignoring return value, as it's mostly not interesting, |
844 |
struct node *dir, char *name) |
struct node *dir, char *name) |
845 |
{ |
{ |
846 |
FUNC_PROLOGUE("netfs_attempt_rmdir"); |
FUNC_PROLOGUE("netfs_attempt_rmdir"); |
847 |
error_t err = EOPNOTSUPP; |
error_t err; |
848 |
struct node *node = NULL; |
struct node *node = NULL; |
849 |
|
|
|
if(! FUSE_OP_HAVE(rmdir)) |
|
|
goto out_nounlock; |
|
|
|
|
850 |
err = netfs_attempt_lookup(user, dir, name, &node); |
err = netfs_attempt_lookup(user, dir, name, &node); |
851 |
assert(dir != node); |
assert(dir != node); |
852 |
mutex_lock(&dir->lock); /* netfs_attempt_lookup unlocked dir */ |
mutex_lock(&dir->lock); /* netfs_attempt_lookup unlocked dir */ |
858 |
|| (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user))) |
|| (err = fshelp_checkdirmod(&dir->nn_stat, &node->nn_stat, user))) |
859 |
goto out; |
goto out; |
860 |
|
|
861 |
err = -FUSE_OP_CALL(rmdir, node->nn->path); |
if(FUSE_OP_HAVE(rmdir)) |
862 |
|
err = -FUSE_OP_CALL(rmdir, node->nn->path); |
863 |
|
else |
864 |
|
err = EOPNOTSUPP; |
865 |
|
|
866 |
|
|
867 |
/* TODO free associated netnode. really? |
/* TODO free associated netnode. really? |
868 |
* FIXME, make sure nn->may_need_sync is set */ |
* FIXME, make sure nn->may_need_sync is set */ |
897 |
char *name) |
char *name) |
898 |
{ |
{ |
899 |
FUNC_PROLOGUE_NODE("netfs_attempt_mksymlink", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_mksymlink", node); |
900 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
/* we need to unlink the existing node, therefore, if unlink is not |
|
|
* available, we cannot create symlinks |
|
|
*/ |
|
|
if(! FUSE_OP_HAVE(unlink)) |
|
|
goto out; |
|
|
|
|
|
/* symlink function available? if not, fail. */ |
|
|
if(! FUSE_OP_HAVE(symlink)) |
|
|
goto out; |
|
901 |
|
|
902 |
/* check permissions |
/* check permissions |
903 |
* XXX, shall we check permissions of the parent directory as well, |
* XXX, shall we check permissions of the parent directory as well, |
904 |
* since we're going to unlink files? |
* since we're going to unlink files? |
905 |
*/ |
*/ |
|
|
|
906 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
907 |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
908 |
goto out; |
goto out; |
909 |
|
|
910 |
|
/* we need to unlink the existing node, therefore, if unlink is not |
911 |
|
* available, we cannot create symlinks |
912 |
|
*/ |
913 |
|
if(! FUSE_OP_HAVE(unlink)) |
914 |
|
{ |
915 |
|
err = EOPNOTSUPP; |
916 |
|
goto out; |
917 |
|
} |
918 |
|
|
919 |
|
/* symlink function available? if not, fail. */ |
920 |
|
if(! FUSE_OP_HAVE(symlink)) |
921 |
|
{ |
922 |
|
err = EOPNOTSUPP; |
923 |
|
goto out; |
924 |
|
} |
925 |
|
|
926 |
/* try to remove the existing node (probably an anonymous file) */ |
/* try to remove the existing node (probably an anonymous file) */ |
927 |
if((err = -FUSE_OP_CALL(unlink, node->nn->path))) |
if((err = -FUSE_OP_CALL(unlink, node->nn->path))) |
928 |
goto out; |
goto out; |
947 |
char *toname, int excl) |
char *toname, int excl) |
948 |
{ |
{ |
949 |
FUNC_PROLOGUE("netfs_attempt_rename"); |
FUNC_PROLOGUE("netfs_attempt_rename"); |
950 |
error_t err = EOPNOTSUPP; |
error_t err; |
951 |
struct node *fromnode; |
struct node *fromnode; |
952 |
char *topath = NULL; |
char *topath = NULL; |
953 |
|
|
|
if(! FUSE_OP_HAVE(rename)) |
|
|
goto out_nounlock; |
|
|
|
|
954 |
if(! (topath = malloc(strlen(toname) + strlen(todir->nn->path) + 2))) |
if(! (topath = malloc(strlen(toname) + strlen(todir->nn->path) + 2))) |
955 |
{ |
{ |
956 |
err = ENOMEM; |
err = ENOMEM; |
977 |
|| fshelp_checkdirmod(&todir->nn_stat, NULL, user)) |
|| fshelp_checkdirmod(&todir->nn_stat, NULL, user)) |
978 |
goto out; |
goto out; |
979 |
|
|
980 |
|
if(! FUSE_OP_HAVE(rename)) |
981 |
|
{ |
982 |
|
err = EOPNOTSUPP; |
983 |
|
goto out; |
984 |
|
} |
985 |
|
|
986 |
sprintf(topath, "%s/%s", todir->nn->path, toname); |
sprintf(topath, "%s/%s", todir->nn->path, toname); |
987 |
|
|
988 |
if(! excl && FUSE_OP_HAVE(unlink)) |
if(! excl && FUSE_OP_HAVE(unlink)) |
1025 |
loff_t offset, size_t *len, void *data) |
loff_t offset, size_t *len, void *data) |
1026 |
{ |
{ |
1027 |
FUNC_PROLOGUE_NODE("netfs_attempt_write", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_write", node); |
1028 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
if(! FUSE_OP_HAVE(write)) |
|
|
goto out; |
|
1029 |
|
|
1030 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
1031 |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
|| (err = fshelp_access(&node->nn_stat, S_IWRITE, cred))) |
1032 |
goto out; |
goto out; |
1033 |
|
|
1034 |
|
if(! FUSE_OP_HAVE(write)) |
1035 |
|
{ |
1036 |
|
err = EOPNOTSUPP; |
1037 |
|
goto out; |
1038 |
|
} |
1039 |
|
|
1040 |
node->nn->info.writepage = 0; /* cannot distinct on the Hurd :( */ |
node->nn->info.writepage = 0; /* cannot distinct on the Hurd :( */ |
1041 |
|
|
1042 |
int sz = fuse_ops ? |
int sz = fuse_ops ? |
1061 |
struct timespec *atime, struct timespec *mtime) |
struct timespec *atime, struct timespec *mtime) |
1062 |
{ |
{ |
1063 |
FUNC_PROLOGUE_NODE("netfs_attempt_utimes", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_utimes", node); |
1064 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
/* prepare utimebuf for FUSE_OP_HAVE(utime) call */ |
|
|
struct utimbuf utb; |
|
|
utb.actime = atime ? atime->tv_sec : node->nn_stat.st_atime; |
|
|
utb.modtime = mtime ? mtime->tv_sec : node->nn_stat.st_mtime; |
|
1065 |
|
|
1066 |
/* test whether operation is supported and permission are sufficient */ |
/* test whether operation is supported and permission are sufficient */ |
|
if(! FUSE_OP_HAVE(utime)) |
|
|
goto out; |
|
|
|
|
1067 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
1068 |
|| (err = fshelp_isowner(&node->nn_stat, cred))) |
|| (err = fshelp_isowner(&node->nn_stat, cred))) |
1069 |
goto out; |
goto out; |
1070 |
|
|
1071 |
|
if(! FUSE_OP_HAVE(utime)) |
1072 |
|
{ |
1073 |
|
err = EOPNOTSUPP; |
1074 |
|
goto out; |
1075 |
|
} |
1076 |
|
|
1077 |
|
/* prepare utimebuf for FUSE_OP_HAVE(utime) call */ |
1078 |
|
struct utimbuf utb; |
1079 |
|
utb.actime = atime ? atime->tv_sec : node->nn_stat.st_atime; |
1080 |
|
utb.modtime = mtime ? mtime->tv_sec : node->nn_stat.st_mtime; |
1081 |
|
|
1082 |
err = -FUSE_OP_CALL(utime, node->nn->path, &utb); |
err = -FUSE_OP_CALL(utime, node->nn->path, &utb); |
1083 |
|
|
1084 |
if (! err) |
if (! err) |
1105 |
loff_t offset, size_t *len, void *data) |
loff_t offset, size_t *len, void *data) |
1106 |
{ |
{ |
1107 |
FUNC_PROLOGUE_NODE("netfs_attempt_read", node); |
FUNC_PROLOGUE_NODE("netfs_attempt_read", node); |
1108 |
error_t err = EOPNOTSUPP; |
error_t err; |
|
|
|
|
if(! FUSE_OP_HAVE(read)) |
|
|
goto out; |
|
1109 |
|
|
1110 |
if((err = netfs_validate_stat(node, cred)) |
if((err = netfs_validate_stat(node, cred)) |
1111 |
|| (err = fshelp_access(&node->nn_stat, S_IREAD, cred))) |
|| (err = fshelp_access(&node->nn_stat, S_IREAD, cred))) |
1112 |
goto out; |
goto out; |
1113 |
|
|
1114 |
|
if(! FUSE_OP_HAVE(read)) |
1115 |
|
{ |
1116 |
|
err = EOPNOTSUPP; |
1117 |
|
goto out; |
1118 |
|
} |
1119 |
|
|
1120 |
|
|
1121 |
int sz = fuse_ops ? |
int sz = fuse_ops ? |
1122 |
(fuse_ops->read(node->nn->path, data, *len, offset, &node->nn->info)) : |
(fuse_ops->read(node->nn->path, data, *len, offset, &node->nn->info)) : |
1123 |
(fuse_ops_compat->read(node->nn->path, data, *len, offset)); |
(fuse_ops_compat->read(node->nn->path, data, *len, offset)); |
1284 |
* i.e. never allocate any further memory */ |
* i.e. never allocate any further memory */ |
1285 |
|
|
1286 |
FUNC_PROLOGUE_NODE("netfs_get_dirents", dir); |
FUNC_PROLOGUE_NODE("netfs_get_dirents", dir); |
1287 |
error_t err = EOPNOTSUPP; |
error_t err; |
1288 |
fuse_dirh_t handle; |
fuse_dirh_t handle; |
1289 |
|
|
|
if(! FUSE_OP_HAVE(getdir)) |
|
|
goto out; |
|
|
|
|
1290 |
if((err = netfs_validate_stat(dir, cred)) |
if((err = netfs_validate_stat(dir, cred)) |
1291 |
|| (err = fshelp_access(&dir->nn_stat, S_IREAD, cred)) |
|| (err = fshelp_access(&dir->nn_stat, S_IREAD, cred)) |
1292 |
|| (err = fshelp_access(&dir->nn_stat, S_IEXEC, cred))) |
|| (err = fshelp_access(&dir->nn_stat, S_IEXEC, cred))) |
1293 |
goto out; |
goto out; |
1294 |
|
|
1295 |
|
if(! FUSE_OP_HAVE(getdir)) |
1296 |
|
{ |
1297 |
|
err = EOPNOTSUPP; |
1298 |
|
goto out; |
1299 |
|
} |
1300 |
|
|
1301 |
if(! (handle = malloc(sizeof(struct fuse_dirhandle)))) |
if(! (handle = malloc(sizeof(struct fuse_dirhandle)))) |
1302 |
{ |
{ |
1303 |
err = ENOMEM; /* sorry, translator not available ... */ |
err = ENOMEM; /* sorry, translator not available ... */ |