[BACK]Return to refuse.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / librefuse

Annotation of src/lib/librefuse/refuse.c, Revision 1.52

1.52    ! agc         1: /*     $NetBSD: refuse.c,v 1.51 2007/05/03 21:02:54 agc Exp $  */
1.7       pooka       2:
1.1       agc         3: /*
                      4:  * Copyright © 2007 Alistair Crooks.  All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. The name of the author may not be used to endorse or promote
                     15:  *    products derived from this software without specific prior written
                     16:  *    permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     19:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     20:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     21:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
                     22:  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     23:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
                     24:  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     25:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     26:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                     27:  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
                     28:  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     29:  */
1.7       pooka      30:
                     31: #include <sys/cdefs.h>
                     32: #if !defined(lint)
1.52    ! agc        33: __RCSID("$NetBSD: refuse.c,v 1.51 2007/05/03 21:02:54 agc Exp $");
1.7       pooka      34: #endif /* !lint */
                     35:
1.25      pooka      36: #include <assert.h>
1.1       agc        37: #include <err.h>
                     38: #include <errno.h>
                     39: #include <fuse.h>
                     40: #include <unistd.h>
                     41:
                     42: #include "defs.h"
                     43:
                     44: typedef uint64_t        fuse_ino_t;
                     45:
                     46: struct fuse_config {
                     47:        uid_t           uid;
                     48:        gid_t           gid;
                     49:        mode_t          umask;
                     50:        double          entry_timeout;
                     51:        double          negative_timeout;
                     52:        double          attr_timeout;
                     53:        double          ac_attr_timeout;
                     54:        int             ac_attr_timeout_set;
                     55:        int             debug;
                     56:        int             hard_remove;
                     57:        int             use_ino;
                     58:        int             readdir_ino;
                     59:        int             set_mode;
                     60:        int             set_uid;
                     61:        int             set_gid;
                     62:        int             direct_io;
                     63:        int             kernel_cache;
                     64:        int             auto_cache;
                     65:        int             intr;
                     66:        int             intr_signal;
                     67: };
                     68:
1.38      pooka      69: struct fuse_chan {
1.51      agc        70:        const char              *dir;
                     71:        struct fuse_args        *args;
                     72:        struct puffs_usermount  *pu;
1.38      pooka      73: };
                     74:
1.1       agc        75: /* this is the private fuse structure */
                     76: struct fuse {
1.38      pooka      77:        struct fuse_chan        *fc;            /* fuse channel pointer */
1.1       agc        78:        struct fuse_operations  op;             /* switch table of operations */
1.7       pooka      79:        int                     compat;         /* compat level -
                     80:                                                 * not used in puffs_fuse */
1.1       agc        81:        struct node             **name_table;
                     82:        size_t                  name_table_size;
                     83:        struct node             **id_table;
                     84:        size_t                  id_table_size;
                     85:        fuse_ino_t              ctr;
                     86:        unsigned int            generation;
                     87:        unsigned int            hidectr;
                     88:        pthread_mutex_t         lock;
                     89:        pthread_rwlock_t        tree_lock;
                     90:        void                    *user_data;
                     91:        struct fuse_config      conf;
                     92:        int                     intr_installed;
                     93: };
                     94:
1.36      pooka      95: struct puffs_fuse_dirh {
1.43      agc        96:        void *dbuf;
                     97:        struct dirent *d;
                     98:
                     99:        size_t reslen;
                    100:        size_t bufsize;
1.36      pooka     101: };
                    102:
1.43      agc       103: struct refusenode {
                    104:        struct fuse_file_info   file_info;
                    105:        struct puffs_fuse_dirh  dirh;
                    106:        int opencount;
                    107:        int flags;
                    108: };
1.30      pooka     109: #define RN_ROOT                0x01
1.31      pooka     110: #define RN_OPEN                0x02    /* XXX: could just use opencount */
1.5       pooka     111:
1.43      agc       112: static int fuse_setattr(struct fuse *, struct puffs_node *,
                    113:                        const char *, const struct vattr *);
1.26      pooka     114:
1.5       pooka     115: static struct puffs_node *
                    116: newrn(struct puffs_usermount *pu)
                    117: {
                    118:        struct puffs_node *pn;
                    119:        struct refusenode *rn;
                    120:
1.38      pooka     121:        NEW(struct refusenode, rn, "newrn", exit(EXIT_FAILURE));
1.5       pooka     122:        pn = puffs_pn_new(pu, rn);
                    123:
                    124:        return pn;
                    125: }
                    126:
                    127: static void
                    128: nukern(struct puffs_node *pn)
                    129: {
1.36      pooka     130:        struct refusenode *rn = pn->pn_data;
1.5       pooka     131:
1.36      pooka     132:        free(rn->dirh.dbuf);
                    133:        free(rn);
1.5       pooka     134:        puffs_pn_put(pn);
                    135: }
                    136:
1.1       agc       137: static ino_t fakeino = 3;
                    138:
1.21      pooka     139: /*
1.43      agc       140:  * XXX: do this otherwise if/when we grow thread support
1.21      pooka     141:  *
                    142:  * XXX2: does not consistently supply uid, gid or pid currently
                    143:  */
                    144: static struct fuse_context fcon;
                    145:
1.36      pooka     146: #define DIR_CHUNKSIZE 4096
                    147: static int
                    148: fill_dirbuf(struct puffs_fuse_dirh *dh, const char *name, ino_t dino,
                    149:        uint8_t dtype)
                    150: {
                    151:
                    152:        /* initial? */
                    153:        if (dh->bufsize == 0) {
                    154:                dh->dbuf = malloc(DIR_CHUNKSIZE);
1.43      agc       155:                if (dh->dbuf == NULL)
                    156:                        err(1, "fill_dirbuf");
1.36      pooka     157:                dh->d = dh->dbuf;
                    158:                dh->reslen = dh->bufsize = DIR_CHUNKSIZE;
                    159:        }
1.21      pooka     160:
1.43      agc       161:        if (puffs_nextdent(&dh->d, name, dino, dtype, &dh->reslen))
1.36      pooka     162:                return 0;
                    163:
                    164:        /* try to increase buffer space */
                    165:        dh->dbuf = realloc(dh->dbuf, dh->bufsize + DIR_CHUNKSIZE);
1.43      agc       166:        if (dh->dbuf == NULL)
                    167:                err(1, "fill_dirbuf realloc");
1.36      pooka     168:        dh->d = (void *)((uint8_t *)dh->dbuf + (dh->bufsize - dh->reslen));
                    169:        dh->reslen += DIR_CHUNKSIZE;
                    170:        dh->bufsize += DIR_CHUNKSIZE;
                    171:
                    172:        return !puffs_nextdent(&dh->d, name, dino, dtype, &dh->reslen);
                    173: }
1.1       agc       174:
1.36      pooka     175: /* ARGSUSED3 */
                    176: /* XXX: I have no idea how "off" is supposed to be used */
1.1       agc       177: static int
1.4       pooka     178: puffs_fuse_fill_dir(void *buf, const char *name,
1.1       agc       179:        const struct stat *stbuf, off_t off)
                    180: {
1.36      pooka     181:        struct puffs_fuse_dirh *deh = buf;
1.13      pooka     182:        ino_t dino;
1.1       agc       183:        uint8_t dtype;
                    184:
1.13      pooka     185:        if (stbuf == NULL) {
                    186:                dtype = DT_UNKNOWN;
                    187:                dino = fakeino++;
                    188:        } else {
                    189:                dtype = puffs_vtype2dt(puffs_mode2vt(stbuf->st_mode));
                    190:                dino = stbuf->st_ino;
1.50      pooka     191:
                    192:                /*
                    193:                 * Some FUSE file systems like to always use 0 as the
                    194:                 * inode number.   Our readdir() doesn't like to show
                    195:                 * directory entries with inode number 0 ==> workaround.
                    196:                 */
                    197:                if (dino == 0)
                    198:                        dino = fakeino++;
1.13      pooka     199:        }
1.1       agc       200:
1.36      pooka     201:        return fill_dirbuf(deh, name, dino, dtype);
1.4       pooka     202: }
                    203:
                    204: static int
                    205: puffs_fuse_dirfil(fuse_dirh_t h, const char *name, int type, ino_t ino)
                    206: {
1.43      agc       207:        ino_t dino;
                    208:        int dtype;
1.4       pooka     209:
1.43      agc       210:        if (type == 0)
1.13      pooka     211:                dtype = DT_UNKNOWN;
1.43      agc       212:        else
                    213:                dtype = type;
                    214:
                    215:        if (ino)
                    216:                dino = ino;
                    217:        else
1.4       pooka     218:                dino = fakeino++;
                    219:
1.36      pooka     220:        return fill_dirbuf(h, name, dino, dtype);
1.1       agc       221: }
                    222:
1.51      agc       223: static struct fuse_args *
                    224: deep_copy_args(int argc, char **argv)
                    225: {
                    226:        struct fuse_args        *ap;
                    227:        int                      i;
                    228:
                    229:        NEW(struct fuse_args, ap, "deep_copy_args", return NULL);
                    230:        /* deep copy args structure into channel args */
                    231:        ap->allocated = ((argc / 10) + 1) * 10;
                    232:        NEWARRAY(char *, ap->argv, ap->allocated, "deep_copy_args",
                    233:                return NULL);
                    234:        for (i = 0 ; i < argc ; i++) {
                    235:                ap->argv[i] = strdup(argv[i]);
                    236:        }
                    237:        return ap;
                    238: }
                    239:
                    240: static void
                    241: free_args(struct fuse_args *ap)
                    242: {
                    243:        int     i;
                    244:
                    245:        for (i = 0 ; i < ap->argc ; i++) {
                    246:                free(ap->argv[i]);
                    247:        }
                    248:        free(ap);
                    249: }
                    250:
                    251: /* this function exposes struct fuse to userland */
                    252: struct fuse *
                    253: fuse_setup(int argc, char **argv, const struct fuse_operations *ops,
                    254:        size_t size, char **mountpoint, int *multithreaded, int *fd)
                    255: {
                    256:        struct fuse_chan        *fc;
                    257:        struct fuse_args        *args;
                    258:        struct fuse             *fuse;
                    259:        char                     name[64];
                    260:        char                    *slash;
                    261:
                    262:        /* whilst this (assigning the pu_privdata in the puffs
                    263:         * usermount struct to be the fuse struct) might seem like
                    264:         * we are chasing our tail here, the logic is as follows:
                    265:                + the operation wrapper gets called with the puffs
                    266:                  calling conventions
                    267:                + we need to fix up args first
                    268:                + then call the fuse user-supplied operation
                    269:                + then we fix up any values on return that we need to
                    270:                + and fix up any nodes, etc
                    271:         * so we need to be able to get at the fuse ops from within the
                    272:         * puffs_usermount struct
                    273:         */
                    274:        if (argv == NULL || *argv == NULL) {
                    275:                (void) strlcpy(name, "refuse", sizeof(name));
                    276:        } else {
                    277:                if ((slash = strrchr(*argv, '/')) == NULL) {
                    278:                        slash = *argv;
                    279:                } else {
                    280:                        slash += 1;
                    281:                }
                    282:                (void) snprintf(name, sizeof(name), "refuse:%s", slash);
                    283:        }
                    284:
                    285:        /* stuff name into fuse_args */
                    286:        args = deep_copy_args(argc, argv);
                    287:        if (args->argc > 0) {
                    288:                FREE(args->argv[0]);
                    289:        }
                    290:        args->argv[0] = strdup(name);
                    291:
                    292:        fc = fuse_mount(*mountpoint = argv[argc - 1], args);
                    293:        fuse = fuse_new(fc, args, ops, size, NULL);
                    294:
                    295:        free_args(args);
                    296:
                    297:        /* XXX - wait for puffs to become multi-threaded */
                    298:        if (multithreaded) {
                    299:                *multithreaded = 0;
                    300:        }
                    301:
                    302:        /* XXX - this is unused */
                    303:        if (fd) {
                    304:                *fd = 0;
                    305:        }
                    306:
                    307:        return fuse;
                    308: }
                    309:
1.18      pooka     310: #define FUSE_ERR_UNLINK(fuse, file) if (fuse->op.unlink) fuse->op.unlink(file)
                    311: #define FUSE_ERR_RMDIR(fuse, dir) if (fuse->op.rmdir) fuse->op.rmdir(dir)
                    312:
1.26      pooka     313: /* ARGSUSED1 */
                    314: static int
                    315: fuse_getattr(struct fuse *fuse, struct puffs_node *pn, const char *path,
                    316:        struct vattr *va)
                    317: {
                    318:        struct stat              st;
                    319:        int                     ret;
                    320:
                    321:        if (fuse->op.getattr == NULL) {
                    322:                return ENOSYS;
                    323:        }
                    324:
                    325:        /* wrap up return code */
                    326:        ret = (*fuse->op.getattr)(path, &st);
                    327:
                    328:        if (ret == 0) {
                    329:                puffs_stat2vattr(va, &st);
                    330:        }
                    331:
                    332:        return -ret;
                    333: }
                    334:
                    335: static int
                    336: fuse_setattr(struct fuse *fuse, struct puffs_node *pn, const char *path,
                    337:        const struct vattr *va)
                    338: {
                    339:        struct refusenode       *rn = pn->pn_data;
                    340:        mode_t                  mode;
                    341:        uid_t                   uid;
                    342:        gid_t                   gid;
                    343:        int                     error, ret;
                    344:
                    345:        error = 0;
                    346:
                    347:        mode = va->va_mode;
                    348:        uid = va->va_uid;
                    349:        gid = va->va_gid;
                    350:
                    351:        if (mode != (mode_t)PUFFS_VNOVAL) {
                    352:                ret = 0;
                    353:
                    354:                if (fuse->op.chmod == NULL) {
                    355:                        error = -ENOSYS;
                    356:                } else {
                    357:                        ret = fuse->op.chmod(path, mode);
                    358:                        if (ret)
                    359:                                error = ret;
                    360:                }
                    361:        }
                    362:        if (uid != (uid_t)PUFFS_VNOVAL || gid != (gid_t)PUFFS_VNOVAL) {
                    363:                ret = 0;
                    364:
                    365:                if (fuse->op.chown == NULL) {
                    366:                        error = -ENOSYS;
                    367:                } else {
                    368:                        ret = fuse->op.chown(path, uid, gid);
                    369:                        if (ret)
                    370:                                error = ret;
                    371:                }
                    372:        }
                    373:        if (va->va_atime.tv_sec != (time_t)PUFFS_VNOVAL
                    374:            || va->va_mtime.tv_sec != (long)PUFFS_VNOVAL) {
                    375:                ret = 0;
                    376:
                    377:                if (fuse->op.utimens) {
                    378:                        struct timespec tv[2];
                    379:
                    380:                        tv[0].tv_sec = va->va_atime.tv_sec;
                    381:                        tv[0].tv_nsec = va->va_atime.tv_nsec;
                    382:                        tv[1].tv_sec = va->va_mtime.tv_sec;
                    383:                        tv[1].tv_nsec = va->va_mtime.tv_nsec;
                    384:
                    385:                        ret = fuse->op.utimens(path, tv);
                    386:                } else if (fuse->op.utime) {
                    387:                        struct utimbuf timbuf;
                    388:
                    389:                        timbuf.actime = va->va_atime.tv_sec;
                    390:                        timbuf.modtime = va->va_mtime.tv_sec;
                    391:
                    392:                        ret = fuse->op.utime(path, &timbuf);
                    393:                } else {
                    394:                        error = -ENOSYS;
                    395:                }
                    396:
                    397:                if (ret)
                    398:                        error = ret;
                    399:        }
                    400:        if (va->va_size != (u_quad_t)PUFFS_VNOVAL) {
                    401:                ret = 0;
                    402:
                    403:                if (fuse->op.truncate) {
                    404:                        ret = fuse->op.truncate(path, (off_t)va->va_size);
                    405:                } else if (fuse->op.ftruncate) {
                    406:                        ret = fuse->op.ftruncate(path, (off_t)va->va_size,
                    407:                            &rn->file_info);
                    408:                } else {
                    409:                        error = -ENOSYS;
                    410:                }
                    411:
                    412:                if (ret)
                    413:                        error = ret;
                    414:        }
                    415:        /* XXX: no reflection with reality */
                    416:        puffs_setvattr(&pn->pn_va, va);
                    417:
                    418:        return -error;
                    419:
                    420: }
                    421:
                    422: static int
                    423: fuse_newnode(struct puffs_usermount *pu, const char *path,
                    424:        const struct vattr *va, struct fuse_file_info *fi, void **newnode)
                    425: {
                    426:        struct vattr            newva;
                    427:        struct fuse             *fuse;
                    428:        struct puffs_node       *pn;
                    429:        struct refusenode       *rn;
                    430:
1.46      pooka     431:        fuse = puffs_getspecific(pu);
1.26      pooka     432:
                    433:        /* fix up nodes */
                    434:        pn = newrn(pu);
                    435:        if (pn == NULL) {
                    436:                if (va->va_type == VDIR) {
                    437:                        FUSE_ERR_RMDIR(fuse, path);
                    438:                } else {
                    439:                        FUSE_ERR_UNLINK(fuse, path);
                    440:                }
                    441:                return ENOMEM;
                    442:        }
                    443:        fuse_setattr(fuse, pn, path, va);
                    444:        if (fuse_getattr(fuse, pn, path, &newva) == 0)
                    445:                puffs_setvattr(&pn->pn_va, &newva);
                    446:
                    447:        rn = pn->pn_data;
                    448:        if (fi)
                    449:                memcpy(&rn->file_info, fi, sizeof(struct fuse_file_info));
                    450:
                    451:        *newnode = pn;
                    452:
                    453:        return 0;
                    454: }
                    455:
                    456:
1.1       agc       457: /* operation wrappers start here */
                    458:
                    459: /* lookup the path */
                    460: /* ARGSUSED1 */
                    461: static int
                    462: puffs_fuse_node_lookup(struct puffs_cc *pcc, void *opc, void **newnode,
                    463:        enum vtype *newtype, voff_t *newsize, dev_t *newrdev,
                    464:        const struct puffs_cn *pcn)
                    465: {
                    466:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
1.12      pooka     467:        struct puffs_node       *pn_res;
1.1       agc       468:        struct stat             st;
                    469:        struct fuse             *fuse;
                    470:        const char              *path = PCNPATH(pcn);
                    471:        int                     ret;
                    472:
1.46      pooka     473:        fuse = puffs_getspecific(pu);
1.1       agc       474:        ret = fuse->op.getattr(path, &st);
1.12      pooka     475:
1.1       agc       476:        if (ret != 0) {
1.18      pooka     477:                return -ret;
1.12      pooka     478:        }
                    479:
                    480:        /* XXX: fiXXXme unconst */
                    481:        pn_res = puffs_pn_nodewalk(pu, puffs_path_walkcmp,
                    482:            __UNCONST(&pcn->pcn_po_full));
                    483:        if (pn_res == NULL) {
                    484:                pn_res = newrn(pu);
                    485:                if (pn_res == NULL)
                    486:                        return errno;
1.26      pooka     487:                puffs_stat2vattr(&pn_res->pn_va, &st);
1.1       agc       488:        }
1.12      pooka     489:
                    490:        *newnode = pn_res;
                    491:        *newtype = pn_res->pn_va.va_type;
                    492:        *newsize = pn_res->pn_va.va_size;
                    493:        *newrdev = pn_res->pn_va.va_rdev;
                    494:
                    495:        return 0;
1.1       agc       496: }
                    497:
                    498: /* get attributes for the path name */
                    499: /* ARGSUSED3 */
                    500: static int
                    501: puffs_fuse_node_getattr(struct puffs_cc *pcc, void *opc, struct vattr *va,
                    502:        const struct puffs_cred *pcr, pid_t pid)
                    503: {
                    504:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    505:        struct puffs_node       *pn = opc;
                    506:        struct fuse             *fuse;
                    507:        const char              *path = PNPATH(pn);
                    508:
1.46      pooka     509:        fuse = puffs_getspecific(pu);
1.26      pooka     510:        return fuse_getattr(fuse, pn, path, va);
1.1       agc       511: }
                    512:
                    513: /* read the contents of the symbolic link */
                    514: /* ARGSUSED2 */
                    515: static int
                    516: puffs_fuse_node_readlink(struct puffs_cc *pcc, void *opc,
                    517:        const struct puffs_cred *cred, char *linkname, size_t *linklen)
                    518: {
                    519:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    520:        struct puffs_node       *pn = opc;
                    521:        struct fuse             *fuse;
1.13      pooka     522:        const char              *path = PNPATH(pn), *p;
1.1       agc       523:        int                     ret;
                    524:
1.46      pooka     525:        fuse = puffs_getspecific(pu);
1.1       agc       526:        if (fuse->op.readlink == NULL) {
                    527:                return ENOSYS;
                    528:        }
                    529:
                    530:        /* wrap up return code */
                    531:        ret = (*fuse->op.readlink)(path, linkname, *linklen);
                    532:
                    533:        if (ret == 0) {
1.43      agc       534:                p = memchr(linkname, '\0', *linklen);
1.13      pooka     535:                if (!p)
                    536:                        return EINVAL;
                    537:
1.14      pooka     538:                *linklen = p - linkname;
1.1       agc       539:        }
                    540:
1.13      pooka     541:        return -ret;
1.1       agc       542: }
                    543:
                    544: /* make the special node */
                    545: /* ARGSUSED1 */
                    546: static int
                    547: puffs_fuse_node_mknod(struct puffs_cc *pcc, void *opc, void **newnode,
                    548:        const struct puffs_cn *pcn, const struct vattr *va)
                    549: {
                    550:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    551:        struct fuse             *fuse;
1.44      pooka     552:        mode_t                   mode;
1.1       agc       553:        const char              *path = PCNPATH(pcn);
                    554:        int                     ret;
                    555:
1.46      pooka     556:        fuse = puffs_getspecific(pu);
1.1       agc       557:        if (fuse->op.mknod == NULL) {
                    558:                return ENOSYS;
                    559:        }
                    560:
                    561:        /* wrap up return code */
1.44      pooka     562:        mode = puffs_addvtype2mode(va->va_mode, va->va_type);
1.1       agc       563:        ret = (*fuse->op.mknod)(path, mode, va->va_rdev);
                    564:
                    565:        if (ret == 0) {
1.26      pooka     566:                ret = fuse_newnode(pu, path, va, NULL, newnode);
1.1       agc       567:        }
                    568:
1.18      pooka     569:        return -ret;
1.1       agc       570: }
                    571:
                    572: /* make a directory */
                    573: /* ARGSUSED1 */
                    574: static int
                    575: puffs_fuse_node_mkdir(struct puffs_cc *pcc, void *opc, void **newnode,
                    576:        const struct puffs_cn *pcn, const struct vattr *va)
                    577: {
                    578:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    579:        struct fuse             *fuse;
                    580:        mode_t                   mode = va->va_mode;
                    581:        const char              *path = PCNPATH(pcn);
                    582:        int                     ret;
                    583:
1.46      pooka     584:        fuse = puffs_getspecific(pu);
1.1       agc       585:        if (fuse->op.mkdir == NULL) {
                    586:                return ENOSYS;
                    587:        }
                    588:
                    589:        /* wrap up return code */
                    590:        ret = (*fuse->op.mkdir)(path, mode);
                    591:
                    592:        if (ret == 0) {
1.26      pooka     593:                ret = fuse_newnode(pu, path, va, NULL, newnode);
1.1       agc       594:        }
                    595:
1.18      pooka     596:        return -ret;
1.1       agc       597: }
                    598:
1.21      pooka     599: /*
                    600:  * create a regular file
                    601:  *
                    602:  * since linux/fuse sports using mknod for creating regular files
                    603:  * instead of having a separate call for it in some versions, if
                    604:  * we don't have create, just jump to op->mknod.
                    605:  */
1.16      pooka     606: /*ARGSUSED1*/
                    607: static int
                    608: puffs_fuse_node_create(struct puffs_cc *pcc, void *opc, void **newnode,
                    609:        const struct puffs_cn *pcn, const struct vattr *va)
                    610: {
                    611:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    612:        struct fuse             *fuse;
                    613:        struct fuse_file_info   fi;
                    614:        mode_t                  mode = va->va_mode;
                    615:        const char              *path = PCNPATH(pcn);
1.31      pooka     616:        int                     ret, created;
1.16      pooka     617:
1.46      pooka     618:        fuse = puffs_getspecific(pu);
1.21      pooka     619:
1.31      pooka     620:        created = 0;
1.21      pooka     621:        if (fuse->op.create) {
                    622:                ret = fuse->op.create(path, mode, &fi);
1.31      pooka     623:                if (ret == 0)
                    624:                        created = 1;
1.21      pooka     625:
                    626:        } else if (fuse->op.mknod) {
                    627:                fcon.uid = va->va_uid; /*XXX*/
                    628:                fcon.gid = va->va_gid; /*XXX*/
                    629:
                    630:                ret = fuse->op.mknod(path, mode | S_IFREG, 0);
                    631:
                    632:        } else {
                    633:                ret = -ENOSYS;
1.16      pooka     634:        }
                    635:
                    636:        if (ret == 0) {
1.26      pooka     637:                ret = fuse_newnode(pu, path, va, &fi, newnode);
1.31      pooka     638:
                    639:                /* sweet..  create also open the file */
                    640:                if (created) {
                    641:                        struct puffs_node *pn;
                    642:                        struct refusenode *rn;
                    643:
                    644:                        pn = *newnode;
                    645:                        rn = pn->pn_data;
                    646:                        rn->flags |= RN_OPEN;
                    647:                        rn->opencount++;
                    648:                }
1.16      pooka     649:        }
                    650:
1.18      pooka     651:        return -ret;
1.16      pooka     652: }
                    653:
1.1       agc       654: /* remove the directory entry */
1.23      pooka     655: /* ARGSUSED1 */
1.1       agc       656: static int
                    657: puffs_fuse_node_remove(struct puffs_cc *pcc, void *opc, void *targ,
                    658:        const struct puffs_cn *pcn)
                    659: {
                    660:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
1.23      pooka     661:        struct puffs_node       *pn_targ = targ;
1.1       agc       662:        struct fuse             *fuse;
1.23      pooka     663:        const char              *path = PNPATH(pn_targ);
1.1       agc       664:        int                     ret;
                    665:
1.46      pooka     666:        fuse = puffs_getspecific(pu);
1.1       agc       667:        if (fuse->op.unlink == NULL) {
                    668:                return ENOSYS;
                    669:        }
                    670:
                    671:        /* wrap up return code */
                    672:        ret = (*fuse->op.unlink)(path);
                    673:
1.18      pooka     674:        return -ret;
1.1       agc       675: }
                    676:
                    677: /* remove the directory */
                    678: /* ARGSUSED1 */
                    679: static int
                    680: puffs_fuse_node_rmdir(struct puffs_cc *pcc, void *opc, void *targ,
                    681:        const struct puffs_cn *pcn)
                    682: {
                    683:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
1.23      pooka     684:        struct puffs_node       *pn_targ = targ;
1.1       agc       685:        struct fuse             *fuse;
1.23      pooka     686:        const char              *path = PNPATH(pn_targ);
1.1       agc       687:        int                     ret;
                    688:
1.46      pooka     689:        fuse = puffs_getspecific(pu);
1.1       agc       690:        if (fuse->op.rmdir == NULL) {
                    691:                return ENOSYS;
                    692:        }
                    693:
                    694:        /* wrap up return code */
                    695:        ret = (*fuse->op.rmdir)(path);
                    696:
1.18      pooka     697:        return -ret;
1.1       agc       698: }
                    699:
                    700: /* create a symbolic link */
                    701: /* ARGSUSED1 */
                    702: static int
                    703: puffs_fuse_node_symlink(struct puffs_cc *pcc, void *opc, void **newnode,
                    704:        const struct puffs_cn *pcn_src, const struct vattr *va,
                    705:        const char *link_target)
                    706: {
                    707:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    708:        struct fuse             *fuse;
                    709:        const char              *path = PCNPATH(pcn_src);
                    710:        int                     ret;
                    711:
1.46      pooka     712:        fuse = puffs_getspecific(pu);
1.1       agc       713:        if (fuse->op.symlink == NULL) {
                    714:                return ENOSYS;
                    715:        }
                    716:
                    717:        /* wrap up return code */
1.32      pooka     718:        ret = fuse->op.symlink(link_target, path);
1.1       agc       719:
                    720:        if (ret == 0) {
1.26      pooka     721:                ret = fuse_newnode(pu, path, va, NULL, newnode);
1.1       agc       722:        }
                    723:
1.18      pooka     724:        return -ret;
1.1       agc       725: }
                    726:
                    727: /* rename a directory entry */
                    728: /* ARGSUSED1 */
                    729: static int
                    730: puffs_fuse_node_rename(struct puffs_cc *pcc, void *opc, void *src,
                    731:        const struct puffs_cn *pcn_src, void *targ_dir, void *targ,
                    732:        const struct puffs_cn *pcn_targ)
                    733: {
                    734:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    735:        struct fuse             *fuse;
1.24      pooka     736:        const char              *path_src = PCNPATH(pcn_src);
                    737:        const char              *path_dest = PCNPATH(pcn_targ);
1.1       agc       738:        int                     ret;
                    739:
1.46      pooka     740:        fuse = puffs_getspecific(pu);
1.1       agc       741:        if (fuse->op.rename == NULL) {
                    742:                return ENOSYS;
                    743:        }
                    744:
1.24      pooka     745:        ret = fuse->op.rename(path_src, path_dest);
1.1       agc       746:
                    747:        if (ret == 0) {
                    748:        }
                    749:
1.18      pooka     750:        return -ret;
1.1       agc       751: }
                    752:
                    753: /* create a link in the file system */
                    754: /* ARGSUSED1 */
                    755: static int
                    756: puffs_fuse_node_link(struct puffs_cc *pcc, void *opc, void *targ,
                    757:        const struct puffs_cn *pcn)
                    758: {
                    759:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    760:        struct puffs_node       *pn = targ;
                    761:        struct fuse             *fuse;
                    762:        int                     ret;
                    763:
1.46      pooka     764:        fuse = puffs_getspecific(pu);
1.1       agc       765:        if (fuse->op.link == NULL) {
                    766:                return ENOSYS;
                    767:        }
                    768:
                    769:        /* wrap up return code */
                    770:        ret = (*fuse->op.link)(PNPATH(pn), PCNPATH(pcn));
                    771:
1.18      pooka     772:        return -ret;
1.1       agc       773: }
                    774:
                    775: /*
1.19      pooka     776:  * fuse's regular interface provides chmod(), chown(), utimes()
                    777:  * and truncate() + some variations, so try to fit the square block
                    778:  * in the circle hole and the circle block .... something like that
1.7       pooka     779:  */
1.1       agc       780: /* ARGSUSED3 */
                    781: static int
                    782: puffs_fuse_node_setattr(struct puffs_cc *pcc, void *opc,
                    783:        const struct vattr *va, const struct puffs_cred *pcr, pid_t pid)
                    784: {
                    785:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    786:        struct puffs_node       *pn = opc;
                    787:        struct fuse             *fuse;
                    788:        const char              *path = PNPATH(pn);
                    789:
1.46      pooka     790:        fuse = puffs_getspecific(pu);
1.1       agc       791:
1.26      pooka     792:        return fuse_setattr(fuse, pn, path, va);
1.1       agc       793: }
                    794:
                    795: /* ARGSUSED2 */
                    796: static int
1.31      pooka     797: puffs_fuse_node_open(struct puffs_cc *pcc, void *opc, int mode,
1.1       agc       798:        const struct puffs_cred *cred, pid_t pid)
                    799: {
                    800:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    801:        struct puffs_node       *pn = opc;
1.5       pooka     802:        struct refusenode       *rn = pn->pn_data;
1.31      pooka     803:        struct fuse_file_info   *fi = &rn->file_info;
1.1       agc       804:        struct fuse             *fuse;
                    805:        const char              *path = PNPATH(pn);
                    806:
1.46      pooka     807:        fuse = puffs_getspecific(pu);
1.1       agc       808:
1.30      pooka     809:        /* if open, don't open again, lest risk nuking file private info */
1.31      pooka     810:        if (rn->flags & RN_OPEN) {
                    811:                rn->opencount++;
1.1       agc       812:                return 0;
1.31      pooka     813:        }
1.1       agc       814:
1.37      pooka     815:        /* OFLAGS(), need to convert FREAD/FWRITE to O_RD/WR */
                    816:        fi->flags = (mode & ~(O_CREAT | O_EXCL | O_TRUNC)) - 1;
                    817:
1.30      pooka     818:        if (pn->pn_va.va_type == VDIR) {
                    819:                if (fuse->op.opendir)
1.33      pooka     820:                        fuse->op.opendir(path, fi);
1.30      pooka     821:        } else {
                    822:                if (fuse->op.open)
1.33      pooka     823:                        fuse->op.open(path, fi);
1.30      pooka     824:        }
1.1       agc       825:
1.33      pooka     826:        rn->flags |= RN_OPEN;
                    827:        rn->opencount++;
1.1       agc       828:
1.33      pooka     829:        return 0;
1.1       agc       830: }
                    831:
1.31      pooka     832: /* ARGSUSED2 */
                    833: static int
                    834: puffs_fuse_node_close(struct puffs_cc *pcc, void *opc, int fflag,
                    835:        const struct puffs_cred *pcr, pid_t pid)
                    836: {
                    837:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    838:        struct puffs_node       *pn = opc;
                    839:        struct refusenode       *rn = pn->pn_data;
                    840:        struct fuse             *fuse;
                    841:        struct fuse_file_info   *fi;
                    842:        const char              *path = PNPATH(pn);
                    843:        int                     ret;
                    844:
1.46      pooka     845:        fuse = puffs_getspecific(pu);
1.31      pooka     846:        fi = &rn->file_info;
                    847:        ret = 0;
                    848:
                    849:        if (rn->flags & RN_OPEN) {
                    850:                if (pn->pn_va.va_type == VDIR) {
                    851:                        if (fuse->op.releasedir)
                    852:                                ret = fuse->op.releasedir(path, fi);
                    853:                } else {
                    854:                        if (fuse->op.release)
                    855:                                ret = fuse->op.release(path, fi);
                    856:                }
                    857:        }
                    858:        rn->flags &= ~RN_OPEN;
                    859:        rn->opencount--;
                    860:
                    861:        return ret;
                    862: }
                    863:
1.1       agc       864: /* read some more from the file */
                    865: /* ARGSUSED5 */
                    866: static int
                    867: puffs_fuse_node_read(struct puffs_cc *pcc, void *opc, uint8_t *buf,
                    868:        off_t offset, size_t *resid, const struct puffs_cred *pcr,
                    869:        int ioflag)
                    870: {
                    871:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    872:        struct puffs_node       *pn = opc;
1.5       pooka     873:        struct refusenode       *rn = pn->pn_data;
1.1       agc       874:        struct fuse             *fuse;
                    875:        const char              *path = PNPATH(pn);
1.25      pooka     876:        size_t                  maxread;
1.1       agc       877:        int                     ret;
                    878:
1.46      pooka     879:        fuse = puffs_getspecific(pu);
1.1       agc       880:        if (fuse->op.read == NULL) {
                    881:                return ENOSYS;
                    882:        }
                    883:
1.25      pooka     884:        maxread = *resid;
1.26      pooka     885:        if (maxread > pn->pn_va.va_size - offset) {
                    886:                /*LINTED*/
1.25      pooka     887:                maxread = pn->pn_va.va_size - offset;
1.26      pooka     888:        }
1.25      pooka     889:        if (maxread == 0)
                    890:                return 0;
                    891:
                    892:        ret = (*fuse->op.read)(path, (char *)buf, maxread, offset,
1.7       pooka     893:            &rn->file_info);
1.1       agc       894:
                    895:        if (ret > 0) {
                    896:                *resid -= ret;
1.16      pooka     897:                ret = 0;
1.1       agc       898:        }
                    899:
1.16      pooka     900:        return -ret;
1.1       agc       901: }
                    902:
                    903: /* write to the file */
                    904: /* ARGSUSED0 */
                    905: static int
                    906: puffs_fuse_node_write(struct puffs_cc *pcc, void *opc, uint8_t *buf,
                    907:        off_t offset, size_t *resid, const struct puffs_cred *pcr,
                    908:        int ioflag)
                    909: {
                    910:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    911:        struct puffs_node       *pn = opc;
1.8       pooka     912:        struct refusenode       *rn = pn->pn_data;
1.1       agc       913:        struct fuse             *fuse;
                    914:        const char              *path = PNPATH(pn);
                    915:        int                     ret;
                    916:
1.46      pooka     917:        fuse = puffs_getspecific(pu);
1.1       agc       918:        if (fuse->op.write == NULL) {
                    919:                return ENOSYS;
                    920:        }
                    921:
1.17      pooka     922:        if (ioflag & PUFFS_IO_APPEND)
                    923:                offset = pn->pn_va.va_size;
                    924:
1.8       pooka     925:        ret = (*fuse->op.write)(path, (char *)buf, *resid, offset,
                    926:            &rn->file_info);
1.1       agc       927:
                    928:        if (ret > 0) {
1.23      pooka     929:                if (offset + ret > pn->pn_va.va_size)
                    930:                        pn->pn_va.va_size = offset + ret;
1.26      pooka     931:                *resid -= ret;
1.16      pooka     932:                ret = 0;
1.1       agc       933:        }
                    934:
1.16      pooka     935:        return -ret;
1.1       agc       936: }
                    937:
                    938:
                    939: /* ARGSUSED3 */
                    940: static int
1.45      pooka     941: puffs_fuse_node_readdir(struct puffs_cc *pcc, void *opc, struct dirent *dent,
                    942:        off_t *readoff, size_t *reslen, const struct puffs_cred *pcr,
                    943:        int *eofflag, off_t *cookies, size_t *ncookies)
1.1       agc       944: {
                    945:        struct puffs_usermount  *pu = puffs_cc_getusermount(pcc);
                    946:        struct puffs_node       *pn = opc;
1.8       pooka     947:        struct refusenode       *rn = pn->pn_data;
1.43      agc       948:        struct puffs_fuse_dirh  *dirh;
                    949:        struct fuse             *fuse;
1.41      agc       950:        struct dirent           *fromdent;
1.1       agc       951:        const char              *path = PNPATH(pn);
                    952:        int                     ret;
                    953:
1.46      pooka     954:        fuse = puffs_getspecific(pu);
1.4       pooka     955:        if (fuse->op.readdir == NULL && fuse->op.getdir == NULL) {
1.1       agc       956:                return ENOSYS;
                    957:        }
                    958:
1.36      pooka     959:        if (pn->pn_va.va_type != VDIR)
                    960:                return ENOTDIR;
                    961:
                    962:        dirh = &rn->dirh;
                    963:
                    964:        /*
                    965:         * if we are starting from the beginning, slurp entire directory
                    966:         * into our buffers
                    967:         */
                    968:        if (*readoff == 0) {
                    969:                /* free old buffers */
                    970:                free(dirh->dbuf);
                    971:                memset(dirh, 0, sizeof(struct puffs_fuse_dirh));
                    972:
                    973:                if (fuse->op.readdir)
                    974:                        ret = fuse->op.readdir(path, dirh, puffs_fuse_fill_dir,
                    975:                            0, &rn->file_info);
                    976:                else
                    977:                        ret = fuse->op.getdir(path, dirh, puffs_fuse_dirfil);
                    978:                if (ret)
                    979:                        return -ret;
1.35      pooka     980:        }
                    981:
1.36      pooka     982:        /* now, stuff results into the kernel buffers */
                    983:        while (*readoff < dirh->bufsize - dirh->reslen) {
                    984:                /*LINTED*/
                    985:                fromdent = (struct dirent *)((uint8_t *)dirh->dbuf + *readoff);
                    986:
                    987:                if (*reslen < _DIRENT_SIZE(fromdent))
                    988:                        break;
                    989:
                    990:                memcpy(dent, fromdent, _DIRENT_SIZE(fromdent));
                    991:                *readoff += _DIRENT_SIZE(fromdent);
                    992:                *reslen -= _DIRENT_SIZE(fromdent);
1.1       agc       993:
1.36      pooka     994:                dent = _DIRENT_NEXT(dent);
1.1       agc       995:        }
                    996:
1.36      pooka     997:        return 0;
1.1       agc       998: }
                    999:
1.26      pooka    1000: /* ARGSUSED */
                   1001: static int
                   1002: puffs_fuse_node_reclaim(struct puffs_cc *pcc, void *opc, pid_t pid)
                   1003: {
                   1004:        struct puffs_node       *pn = opc;
1.3       pooka    1005:
1.5       pooka    1006:        nukern(pn);
1.3       pooka    1007:
1.26      pooka    1008:        return 0;
1.3       pooka    1009: }
                   1010:
1.1       agc      1011: /* ARGSUSED1 */
                   1012: static int
                   1013: puffs_fuse_fs_unmount(struct puffs_cc *pcc, int flags, pid_t pid)
                   1014: {
                   1015:         struct puffs_usermount *pu = puffs_cc_getusermount(pcc);
                   1016:        struct fuse             *fuse;
                   1017:
1.46      pooka    1018:        fuse = puffs_getspecific(pu);
1.1       agc      1019:        if (fuse->op.destroy == NULL) {
1.2       pooka    1020:                return 0;
1.1       agc      1021:        }
                   1022:        (*fuse->op.destroy)(fuse);
                   1023:         return 0;
                   1024: }
                   1025:
                   1026: /* ARGSUSED0 */
                   1027: static int
                   1028: puffs_fuse_fs_sync(struct puffs_cc *pcc, int flags,
                   1029:             const struct puffs_cred *cr, pid_t pid)
                   1030: {
                   1031:         return 0;
                   1032: }
                   1033:
                   1034: /* ARGSUSED2 */
                   1035: static int
                   1036: puffs_fuse_fs_statvfs(struct puffs_cc *pcc, struct statvfs *svfsb, pid_t pid)
                   1037: {
                   1038:         struct puffs_usermount *pu = puffs_cc_getusermount(pcc);
                   1039:        struct fuse             *fuse;
                   1040:        int                     ret;
                   1041:
1.46      pooka    1042:        fuse = puffs_getspecific(pu);
1.1       agc      1043:        if (fuse->op.statfs == NULL) {
1.46      pooka    1044:                if ((ret = statvfs(PNPATH(puffs_getroot(pu)), svfsb)) == -1) {
1.1       agc      1045:                        return errno;
                   1046:                }
                   1047:        } else {
1.46      pooka    1048:                ret = fuse->op.statfs(PNPATH(puffs_getroot(pu)), svfsb);
1.1       agc      1049:        }
                   1050:
                   1051:         return ret;
                   1052: }
                   1053:
                   1054:
                   1055: /* End of puffs_fuse operations */
                   1056: /* ARGSUSED3 */
                   1057: int
                   1058: fuse_main_real(int argc, char **argv, const struct fuse_operations *ops,
                   1059:        size_t size, void *userdata)
                   1060: {
1.51      agc      1061:        struct fuse     *fuse;
                   1062:        char            *mountpoint;
                   1063:        int              multithreaded;
                   1064:        int              fd;
1.38      pooka    1065:
1.51      agc      1066:        fuse = fuse_setup(argc, argv, ops, size, &mountpoint, &multithreaded,
                   1067:                        &fd);
1.38      pooka    1068:
1.51      agc      1069:        return fuse_loop(fuse);
1.38      pooka    1070: }
                   1071:
                   1072: /*
                   1073:  * XXX: just defer the operation until fuse_new() when we have more
                   1074:  * info on our hands.  The real beef is why's this separate in fuse in
                   1075:  * the first place?
                   1076:  */
                   1077: /* ARGSUSED1 */
                   1078: struct fuse_chan *
                   1079: fuse_mount(const char *dir, struct fuse_args *args)
                   1080: {
1.48      agc      1081:        struct fuse_chan        *fc;
1.38      pooka    1082:
1.43      agc      1083:        NEW(struct fuse_chan, fc, "fuse_mount", exit(EXIT_FAILURE));
1.38      pooka    1084:
1.43      agc      1085:        fc->dir = strdup(dir);
1.48      agc      1086:
                   1087:        /*
                   1088:         * we need to deep copy the args struct - some fuse file
                   1089:         * systems "clean up" the argument vector for "security
                   1090:         * reasons"
                   1091:         */
                   1092:        fc->args = deep_copy_args(args->argc, args->argv);
1.43      agc      1093:
1.38      pooka    1094:        return fc;
                   1095: }
                   1096:
                   1097: /* ARGSUSED1 */
                   1098: struct fuse *
                   1099: fuse_new(struct fuse_chan *fc, struct fuse_args *args,
                   1100:        const struct fuse_operations *ops, size_t size, void *userdata)
                   1101: {
1.1       agc      1102:        struct puffs_usermount  *pu;
                   1103:        struct puffs_pathobj    *po_root;
1.46      pooka    1104:        struct puffs_node       *pn_root;
1.43      agc      1105:        struct puffs_ops        *pops;
1.41      agc      1106:        struct refusenode       *rn_root;
1.1       agc      1107:        struct statvfs          svfsb;
1.25      pooka    1108:        struct stat             st;
1.1       agc      1109:        struct fuse             *fuse;
1.38      pooka    1110:
                   1111:        NEW(struct fuse, fuse, "fuse_new", exit(EXIT_FAILURE));
                   1112:
                   1113:        /* copy fuse ops to their own stucture */
                   1114:        (void) memcpy(&fuse->op, ops, sizeof(fuse->op));
                   1115:
                   1116:        fcon.fuse = fuse;
                   1117:        fcon.private_data = userdata;
                   1118:
                   1119:        fuse->fc = fc;
1.1       agc      1120:
                   1121:        /* initialise the puffs operations structure */
                   1122:         PUFFSOP_INIT(pops);
                   1123:
                   1124:         PUFFSOP_SET(pops, puffs_fuse, fs, sync);
                   1125:         PUFFSOP_SET(pops, puffs_fuse, fs, statvfs);
                   1126:         PUFFSOP_SET(pops, puffs_fuse, fs, unmount);
                   1127:
1.2       pooka    1128:        /*
                   1129:         * XXX: all of these don't possibly need to be
                   1130:         * unconditionally set
                   1131:         */
1.1       agc      1132:         PUFFSOP_SET(pops, puffs_fuse, node, lookup);
                   1133:         PUFFSOP_SET(pops, puffs_fuse, node, getattr);
1.15      pooka    1134:         PUFFSOP_SET(pops, puffs_fuse, node, setattr);
1.1       agc      1135:         PUFFSOP_SET(pops, puffs_fuse, node, readdir);
                   1136:         PUFFSOP_SET(pops, puffs_fuse, node, readlink);
                   1137:         PUFFSOP_SET(pops, puffs_fuse, node, mknod);
1.16      pooka    1138:         PUFFSOP_SET(pops, puffs_fuse, node, create);
1.15      pooka    1139:         PUFFSOP_SET(pops, puffs_fuse, node, remove);
1.1       agc      1140:         PUFFSOP_SET(pops, puffs_fuse, node, mkdir);
                   1141:         PUFFSOP_SET(pops, puffs_fuse, node, rmdir);
                   1142:         PUFFSOP_SET(pops, puffs_fuse, node, symlink);
                   1143:         PUFFSOP_SET(pops, puffs_fuse, node, rename);
                   1144:         PUFFSOP_SET(pops, puffs_fuse, node, link);
                   1145:         PUFFSOP_SET(pops, puffs_fuse, node, open);
1.31      pooka    1146:         PUFFSOP_SET(pops, puffs_fuse, node, close);
1.1       agc      1147:         PUFFSOP_SET(pops, puffs_fuse, node, read);
                   1148:         PUFFSOP_SET(pops, puffs_fuse, node, write);
1.3       pooka    1149:         PUFFSOP_SET(pops, puffs_fuse, node, reclaim);
1.1       agc      1150:
1.38      pooka    1151:        pu = puffs_mount(pops, fc->dir, MNT_NODEV | MNT_NOSUID,
1.48      agc      1152:                         args->argv[0], fuse,
1.38      pooka    1153:                         PUFFS_FLAG_BUILDPATH
1.49      pooka    1154:                           | PUFFS_FLAG_HASHPATH
1.38      pooka    1155:                           | PUFFS_FLAG_OPDUMP
1.47      pooka    1156:                           | PUFFS_KFLAG_NOCACHE);
1.1       agc      1157:        if (pu == NULL) {
1.52    ! agc      1158:                err(EXIT_FAILURE, "puffs_mount: directory \"%s\"", fc->dir);
1.1       agc      1159:        }
1.38      pooka    1160:        fc->pu = pu;
1.1       agc      1161:
1.46      pooka    1162:        pn_root = newrn(pu);
                   1163:        puffs_setroot(pu, pn_root);
                   1164:        rn_root = pn_root->pn_data;
1.30      pooka    1165:        rn_root->flags |= RN_ROOT;
                   1166:
1.1       agc      1167:        po_root = puffs_getrootpathobj(pu);
                   1168:        po_root->po_path = strdup("/");
                   1169:        po_root->po_len = 1;
                   1170:
1.25      pooka    1171:        /* sane defaults */
1.46      pooka    1172:        puffs_vattr_null(&pn_root->pn_va);
                   1173:        pn_root->pn_va.va_type = VDIR;
                   1174:        pn_root->pn_va.va_mode = 0755;
1.25      pooka    1175:        if (fuse->op.getattr)
                   1176:                if (fuse->op.getattr(po_root->po_path, &st) == 0)
1.46      pooka    1177:                        puffs_stat2vattr(&pn_root->pn_va, &st);
                   1178:        assert(pn_root->pn_va.va_type == VDIR);
1.25      pooka    1179:
1.11      pooka    1180:        if (fuse->op.init)
                   1181:                fcon.private_data = fuse->op.init(NULL); /* XXX */
                   1182:
1.38      pooka    1183:        puffs_zerostatvfs(&svfsb);
1.46      pooka    1184:        if (puffs_start(pu, pn_root, &svfsb) == -1) {
1.1       agc      1185:                err(EXIT_FAILURE, "puffs_start");
                   1186:        }
                   1187:
1.38      pooka    1188:        return fuse;
                   1189: }
                   1190:
                   1191: int
                   1192: fuse_loop(struct fuse *fuse)
                   1193: {
                   1194:
                   1195:        return puffs_mainloop(fuse->fc->pu, PUFFSLOOP_NODAEMON);
                   1196: }
                   1197:
                   1198: void
                   1199: fuse_destroy(struct fuse *fuse)
                   1200: {
                   1201:
1.1       agc      1202:
1.38      pooka    1203:        /* XXXXXX: missing stuff */
1.1       agc      1204:        FREE(fuse);
                   1205: }
                   1206:
1.11      pooka    1207: /* XXX: threads */
                   1208: struct fuse_context *
                   1209: fuse_get_context()
                   1210: {
                   1211:
                   1212:        return &fcon;
                   1213: }
1.20      agc      1214:
                   1215: void
1.38      pooka    1216: fuse_exit(struct fuse *fuse)
1.20      agc      1217: {
                   1218:
1.38      pooka    1219:        puffs_exit(fuse->fc->pu, 1);
1.20      agc      1220: }
1.29      pooka    1221:
                   1222: /*
                   1223:  * XXX: obviously not the most perfect of functions, but needs some
                   1224:  * puffs tweaking for a better tomorrow
                   1225:  */
1.31      pooka    1226: /*ARGSUSED*/
1.29      pooka    1227: void
1.38      pooka    1228: fuse_unmount(const char *mp, struct fuse_chan *fc)
                   1229: {
                   1230:
                   1231:        puffs_exit(fc->pu, 1);
                   1232: }
                   1233:
                   1234: /*ARGSUSED*/
                   1235: void
                   1236: fuse_unmount_compat22(const char *mp)
1.29      pooka    1237: {
                   1238:
                   1239:        return;
                   1240: }
1.51      agc      1241:
                   1242: /* The next function "exposes" struct fuse to userland.  Not much
                   1243: * that we can do about this, as we're conforming to a defined
                   1244: * interface.  */
                   1245:
                   1246: void
                   1247: fuse_teardown(struct fuse *fuse, char *mountpoint)
                   1248: {
                   1249:        fuse_unmount(mountpoint, fuse->fc);
                   1250:        fuse_destroy(fuse);
                   1251: }

CVSweb <webmaster@jp.NetBSD.org>