[BACK]Return to nfs.c CVS log [TXT][DIR] Up to [local] / sys / lib / libsa

Annotation of sys/lib/libsa/nfs.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: nfs.c,v 1.10 2003/08/11 06:23:09 deraadt Exp $        */
                      2: /*     $NetBSD: nfs.c,v 1.19 1996/10/13 02:29:04 christos Exp $        */
                      3:
                      4: /*-
                      5:  *  Copyright (c) 1993 John Brezak
                      6:  *  All rights reserved.
                      7:  *
                      8:  *  Redistribution and use in source and binary forms, with or without
                      9:  *  modification, are permitted provided that the following conditions
                     10:  *  are met:
                     11:  *  1. Redistributions of source code must retain the above copyright
                     12:  *     notice, this list of conditions and the following disclaimer.
                     13:  *  2. Redistributions in binary form must reproduce the above copyright
                     14:  *     notice, this list of conditions and the following disclaimer in the
                     15:  *     documentation and/or other materials provided with the distribution.
                     16:  *  3. The name of the author may not be used to endorse or promote products
                     17:  *     derived from this software without specific prior written permission.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     22:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     23:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     24:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     25:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     27:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     28:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/param.h>
                     33: #include <sys/time.h>
                     34: #include <sys/socket.h>
                     35: #include <sys/stat.h>
                     36:
                     37: #include <netinet/in.h>
                     38: #include <netinet/in_systm.h>
                     39:
                     40: #include "rpcv2.h"
                     41: #include "nfsv2.h"
                     42:
                     43: #include "stand.h"
                     44: #include "saerrno.h"
                     45: #include "net.h"
                     46: #include "netif.h"
                     47: #include "nfs.h"
                     48: #include "rpc.h"
                     49:
                     50: /* Define our own NFS attributes without NQNFS stuff. */
                     51: struct nfsv2_fattrs {
                     52:        n_long  fa_type;
                     53:        n_long  fa_mode;
                     54:        n_long  fa_nlink;
                     55:        n_long  fa_uid;
                     56:        n_long  fa_gid;
                     57:        n_long  fa_size;
                     58:        n_long  fa_blocksize;
                     59:        n_long  fa_rdev;
                     60:        n_long  fa_blocks;
                     61:        n_long  fa_fsid;
                     62:        n_long  fa_fileid;
                     63:        struct nfsv2_time fa_atime;
                     64:        struct nfsv2_time fa_mtime;
                     65:        struct nfsv2_time fa_ctime;
                     66: };
                     67:
                     68:
                     69: struct nfs_read_args {
                     70:        u_char  fh[NFS_FHSIZE];
                     71:        n_long  off;
                     72:        n_long  len;
                     73:        n_long  xxx;                    /* XXX what's this for? */
                     74: };
                     75:
                     76: /* Data part of nfs rpc reply (also the largest thing we receive) */
                     77: #define NFSREAD_SIZE 1024
                     78: struct nfs_read_repl {
                     79:        n_long  errno;
                     80:        struct  nfsv2_fattrs fa;
                     81:        n_long  count;
                     82:        u_char  data[NFSREAD_SIZE];
                     83: };
                     84:
                     85: struct nfs_readlnk_repl {
                     86:        n_long  errno;
                     87:        n_long  len;
                     88:        char    path[NFS_MAXPATHLEN];
                     89: };
                     90:
                     91: struct nfs_iodesc {
                     92:        struct  iodesc  *iodesc;
                     93:        off_t   off;
                     94:        u_char  fh[NFS_FHSIZE];
                     95:        struct nfsv2_fattrs fa; /* all in network order */
                     96: };
                     97:
                     98: struct nfs_iodesc nfs_root_node;
                     99:
                    100:
                    101: /*
                    102:  * Fetch the root file handle (call mount daemon)
                    103:  * On error, return non-zero and set errno.
                    104:  */
                    105: static int
                    106: nfs_getrootfh(struct iodesc *d, char *path, u_char *fhp)
                    107: {
                    108:        int len;
                    109:        struct args {
                    110:                n_long  len;
                    111:                char    path[FNAME_SIZE];
                    112:        } *args;
                    113:        struct repl {
                    114:                n_long  errno;
                    115:                u_char  fh[NFS_FHSIZE];
                    116:        } *repl;
                    117:        struct {
                    118:                n_long  h[RPC_HEADER_WORDS];
                    119:                struct args d;
                    120:        } sdata;
                    121:        struct {
                    122:                n_long  h[RPC_HEADER_WORDS];
                    123:                struct repl d;
                    124:        } rdata;
                    125:        size_t cc;
                    126:
                    127: #ifdef NFS_DEBUG
                    128:        if (debug)
                    129:                printf("nfs_getrootfh: %s\n", path);
                    130: #endif
                    131:
                    132:        args = &sdata.d;
                    133:        repl = &rdata.d;
                    134:
                    135:        bzero(args, sizeof(*args));
                    136:        len = strlen(path);
                    137:        if (len > sizeof(args->path))
                    138:                len = sizeof(args->path);
                    139:        args->len = htonl(len);
                    140:        bcopy(path, args->path, len);
                    141:        len = 4 + roundup(len, 4);
                    142:
                    143:        cc = rpc_call(d, RPCPROG_MNT, RPCMNT_VER1, RPCMNT_MOUNT,
                    144:            args, len, repl, sizeof(*repl));
                    145:        if (cc == -1) {
                    146:                /* errno was set by rpc_call */
                    147:                return (-1);
                    148:        }
                    149:        if (cc < 4) {
                    150:                errno = EBADRPC;
                    151:                return (-1);
                    152:        }
                    153:        if (repl->errno) {
                    154:                errno = ntohl(repl->errno);
                    155:                return (-1);
                    156:        }
                    157:        bcopy(repl->fh, fhp, sizeof(repl->fh));
                    158:        return (0);
                    159: }
                    160:
                    161: /*
                    162:  * Lookup a file.  Store handle and attributes.
                    163:  * Return zero or error number.
                    164:  */
                    165: static int
                    166: nfs_lookupfh(struct nfs_iodesc *d, char *name, struct nfs_iodesc *newfd)
                    167: {
                    168:        int len, rlen;
                    169:        struct args {
                    170:                u_char  fh[NFS_FHSIZE];
                    171:                n_long  len;
                    172:                char    name[FNAME_SIZE];
                    173:        } *args;
                    174:        struct repl {
                    175:                n_long  errno;
                    176:                u_char  fh[NFS_FHSIZE];
                    177:                struct  nfsv2_fattrs fa;
                    178:        } *repl;
                    179:        struct {
                    180:                n_long  h[RPC_HEADER_WORDS];
                    181:                struct args d;
                    182:        } sdata;
                    183:        struct {
                    184:                n_long  h[RPC_HEADER_WORDS];
                    185:                struct repl d;
                    186:        } rdata;
                    187:        ssize_t cc;
                    188:
                    189: #ifdef NFS_DEBUG
                    190:        if (debug)
                    191:                printf("lookupfh: called\n");
                    192: #endif
                    193:
                    194:        args = &sdata.d;
                    195:        repl = &rdata.d;
                    196:
                    197:        bzero(args, sizeof(*args));
                    198:        bcopy(d->fh, args->fh, sizeof(args->fh));
                    199:        len = strlen(name);
                    200:        if (len > sizeof(args->name))
                    201:                len = sizeof(args->name);
                    202:        bcopy(name, args->name, len);
                    203:        args->len = htonl(len);
                    204:        len = 4 + roundup(len, 4);
                    205:        len += NFS_FHSIZE;
                    206:
                    207:        rlen = sizeof(*repl);
                    208:
                    209:        cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_LOOKUP,
                    210:            args, len, repl, rlen);
                    211:        if (cc == -1)
                    212:                return (errno);         /* XXX - from rpc_call */
                    213:        if (cc < 4)
                    214:                return (EIO);
                    215:        if (repl->errno) {
                    216:                /* saerrno.h now matches NFS error numbers. */
                    217:                return (ntohl(repl->errno));
                    218:        }
                    219:        bcopy( repl->fh, &newfd->fh, sizeof(newfd->fh));
                    220:        bcopy(&repl->fa, &newfd->fa, sizeof(newfd->fa));
                    221:        return (0);
                    222: }
                    223:
                    224: /*
                    225:  * Get the destination of a symbolic link.
                    226:  */
                    227: static int
                    228: nfs_readlink(struct nfs_iodesc *d, char *buf)
                    229: {
                    230:        struct {
                    231:                n_long  h[RPC_HEADER_WORDS];
                    232:                u_char fh[NFS_FHSIZE];
                    233:        } sdata;
                    234:        struct {
                    235:                n_long  h[RPC_HEADER_WORDS];
                    236:                struct nfs_readlnk_repl d;
                    237:        } rdata;
                    238:        ssize_t cc;
                    239:
                    240: #ifdef NFS_DEBUG
                    241:        if (debug)
                    242:                printf("readlink: called\n");
                    243: #endif
                    244:
                    245:        bcopy(d->fh, sdata.fh, NFS_FHSIZE);
                    246:        cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READLINK,
                    247:            sdata.fh, NFS_FHSIZE,
                    248:            &rdata.d, sizeof(rdata.d));
                    249:        if (cc == -1)
                    250:                return (errno);
                    251:
                    252:        if (cc < 4)
                    253:                return (EIO);
                    254:
                    255:        if (rdata.d.errno)
                    256:                return (ntohl(rdata.d.errno));
                    257:
                    258:        rdata.d.len = ntohl(rdata.d.len);
                    259:        if (rdata.d.len > NFS_MAXPATHLEN)
                    260:                return (ENAMETOOLONG);
                    261:
                    262:        bcopy(rdata.d.path, buf, rdata.d.len);
                    263:        buf[rdata.d.len] = 0;
                    264:        return (0);
                    265: }
                    266:
                    267: /*
                    268:  * Read data from a file.
                    269:  * Return transfer count or -1 (and set errno)
                    270:  */
                    271: static ssize_t
                    272: nfs_readdata(struct nfs_iodesc *d, off_t off, void *addr, size_t len)
                    273: {
                    274:        struct nfs_read_args *args;
                    275:        struct nfs_read_repl *repl;
                    276:        struct {
                    277:                n_long  h[RPC_HEADER_WORDS];
                    278:                struct nfs_read_args d;
                    279:        } sdata;
                    280:        struct {
                    281:                n_long  h[RPC_HEADER_WORDS];
                    282:                struct nfs_read_repl d;
                    283:        } rdata;
                    284:        size_t cc;
                    285:        long x;
                    286:        int hlen, rlen;
                    287:
                    288:        args = &sdata.d;
                    289:        repl = &rdata.d;
                    290:
                    291:        bcopy(d->fh, args->fh, NFS_FHSIZE);
                    292:        args->off = htonl((n_long)off);
                    293:        if (len > NFSREAD_SIZE)
                    294:                len = NFSREAD_SIZE;
                    295:        args->len = htonl((n_long)len);
                    296:        args->xxx = htonl((n_long)0);
                    297:        hlen = sizeof(*repl) - NFSREAD_SIZE;
                    298:
                    299:        cc = rpc_call(d->iodesc, NFS_PROG, NFS_VER2, NFSPROC_READ,
                    300:            args, sizeof(*args),
                    301:            repl, sizeof(*repl));
                    302:        if (cc == -1) {
                    303:                /* errno was already set by rpc_call */
                    304:                return (-1);
                    305:        }
                    306:        if (cc < hlen) {
                    307:                errno = EBADRPC;
                    308:                return (-1);
                    309:        }
                    310:        if (repl->errno) {
                    311:                errno = ntohl(repl->errno);
                    312:                return (-1);
                    313:        }
                    314:        rlen = cc - hlen;
                    315:        x = ntohl(repl->count);
                    316:        if (rlen < x) {
                    317:                printf("nfsread: short packet, %d < %ld\n", rlen, x);
                    318:                errno = EBADRPC;
                    319:                return(-1);
                    320:        }
                    321:        bcopy(repl->data, addr, x);
                    322:        return (x);
                    323: }
                    324:
                    325: /*
                    326:  * nfs_mount - mount this nfs filesystem to a host
                    327:  * On error, return non-zero and set errno.
                    328:  */
                    329: int
                    330: nfs_mount(int sock, struct in_addr ip, char *path)
                    331: {
                    332:        struct iodesc *desc;
                    333:        struct nfsv2_fattrs *fa;
                    334:
                    335:        if (!(desc = socktodesc(sock))) {
                    336:                errno = EINVAL;
                    337:                return(-1);
                    338:        }
                    339:
                    340:        /* Bind to a reserved port. */
                    341:        desc->myport = htons(--rpc_port);
                    342:        desc->destip = ip;
                    343:        if (nfs_getrootfh(desc, path, nfs_root_node.fh))
                    344:                return (-1);
                    345:        nfs_root_node.iodesc = desc;
                    346:        /* Fake up attributes for the root dir. */
                    347:        fa = &nfs_root_node.fa;
                    348:        fa->fa_type  = htonl(NFDIR);
                    349:        fa->fa_mode  = htonl(0755);
                    350:        fa->fa_nlink = htonl(2);
                    351:
                    352: #ifdef NFS_DEBUG
                    353:        if (debug)
                    354:                printf("nfs_mount: got fh for %s\n", path);
                    355: #endif
                    356:
                    357:        return(0);
                    358: }
                    359:
                    360: /*
                    361:  * Open a file.
                    362:  * return zero or error number
                    363:  */
                    364: int
                    365: nfs_open(char *path, struct open_file *f)
                    366: {
                    367:        struct nfs_iodesc *newfd, *currfd;
                    368:        char namebuf[NFS_MAXPATHLEN + 1], *cp, *ncp;
                    369:        char linkbuf[NFS_MAXPATHLEN + 1];
                    370:        int nlinks = 0, error = 0, c;
                    371:
                    372: #ifdef NFS_DEBUG
                    373:        if (debug)
                    374:                printf("nfs_open: %s\n", path);
                    375: #endif
                    376:        if (nfs_root_node.iodesc == NULL) {
                    377:                printf("nfs_open: must mount first.\n");
                    378:                return (ENXIO);
                    379:        }
                    380:
                    381:        currfd = &nfs_root_node;
                    382:        newfd = 0;
                    383:
                    384:        cp = path;
                    385:        while (*cp) {
                    386:                /*
                    387:                 * Remove extra separators
                    388:                 */
                    389:                while (*cp == '/')
                    390:                        cp++;
                    391:
                    392:                if (*cp == '\0')
                    393:                        break;
                    394:                /*
                    395:                 * Check that current node is a directory.
                    396:                 */
                    397:                if (currfd->fa.fa_type != htonl(NFDIR)) {
                    398:                        error = ENOTDIR;
                    399:                        goto out;
                    400:                }
                    401:
                    402:                /* allocate file system specific data structure */
                    403:                newfd = alloc(sizeof(*newfd));
                    404:                newfd->iodesc = currfd->iodesc;
                    405:                newfd->off = 0;
                    406:
                    407:                /*
                    408:                 * Get next component of path name.
                    409:                 */
                    410:                {
                    411:                        int len = 0;
                    412:
                    413:                        ncp = cp;
                    414:                        while ((c = *cp) != '\0' && c != '/') {
                    415:                                if (++len > NFS_MAXNAMLEN) {
                    416:                                        error = ENOENT;
                    417:                                        goto out;
                    418:                                }
                    419:                                cp++;
                    420:                        }
                    421:                        *cp = '\0';
                    422:                }
                    423:
                    424:                /* lookup a file handle */
                    425:                error = nfs_lookupfh(currfd, ncp, newfd);
                    426:                *cp = c;
                    427:                if (error)
                    428:                        goto out;
                    429:
                    430:                /*
                    431:                 * Check for symbolic link
                    432:                 */
                    433:                if (newfd->fa.fa_type == htonl(NFLNK)) {
                    434:                        int link_len, len;
                    435:
                    436:                        error = nfs_readlink(newfd, linkbuf);
                    437:                        if (error)
                    438:                                goto out;
                    439:
                    440:                        link_len = strlen(linkbuf);
                    441:                        len = strlen(cp);
                    442:
                    443:                        if (link_len + len > MAXPATHLEN ||
                    444:                            ++nlinks > MAXSYMLINKS) {
                    445:                                error = ENOENT;
                    446:                                goto out;
                    447:                        }
                    448:
                    449:                        bcopy(cp, &namebuf[link_len], len + 1);
                    450:                        bcopy(linkbuf, namebuf, link_len);
                    451:
                    452:                        /*
                    453:                         * If absolute pathname, restart at root.
                    454:                         * If relative pathname, restart at parent directory.
                    455:                         */
                    456:                        cp = namebuf;
                    457:                        if (*cp == '/') {
                    458:                                if (currfd != &nfs_root_node)
                    459:                                        free(currfd, sizeof(*currfd));
                    460:                                currfd = &nfs_root_node;
                    461:                        }
                    462:
                    463:                        free(newfd, sizeof(*newfd));
                    464:                        newfd = 0;
                    465:
                    466:                        continue;
                    467:                }
                    468:
                    469:                if (currfd != &nfs_root_node)
                    470:                        free(currfd, sizeof(*currfd));
                    471:                currfd = newfd;
                    472:                newfd = 0;
                    473:        }
                    474:
                    475:        error = 0;
                    476:
                    477: out:
                    478:        if (!error) {
                    479:                f->f_fsdata = (void *)currfd;
                    480:                return (0);
                    481:        }
                    482:
                    483: #ifdef NFS_DEBUG
                    484:        if (debug)
                    485:                printf("nfs_open: %s lookupfh failed: %s\n",
                    486:                    path, strerror(error));
                    487: #endif
                    488:        if (currfd != &nfs_root_node)
                    489:                free(currfd, sizeof(*currfd));
                    490:        if (newfd)
                    491:                free(newfd, sizeof(*newfd));
                    492:
                    493:        return (error);
                    494: }
                    495:
                    496: int
                    497: nfs_close(struct open_file *f)
                    498: {
                    499:        struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
                    500:
                    501: #ifdef NFS_DEBUG
                    502:        if (debug)
                    503:                printf("nfs_close: fp=%p\n", fp);
                    504: #endif
                    505:
                    506:        if (fp)
                    507:                free(fp, sizeof(struct nfs_iodesc));
                    508:        f->f_fsdata = (void *)0;
                    509:
                    510:        return (0);
                    511: }
                    512:
                    513: /*
                    514:  * read a portion of a file
                    515:  */
                    516: int
                    517: nfs_read(struct open_file *f, void *buf, size_t size, size_t *resid)
                    518: {
                    519:        struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
                    520:        ssize_t cc;
                    521:        char *addr = buf;
                    522:
                    523: #ifdef NFS_DEBUG
                    524:        if (debug)
                    525:                printf("nfs_read: size=%d off=%d\n", size, (int)fp->off);
                    526: #endif
                    527:        while ((int)size > 0) {
                    528:                twiddle();
                    529:                cc = nfs_readdata(fp, fp->off, (void *)addr, size);
                    530:                /* XXX maybe should retry on certain errors */
                    531:                if (cc == -1) {
                    532: #ifdef NFS_DEBUG
                    533:                        if (debug)
                    534:                                printf("nfs_read: read: %s", strerror(errno));
                    535: #endif
                    536:                        return (errno); /* XXX - from nfs_readdata */
                    537:                }
                    538:                if (cc == 0) {
                    539:                        if (debug)
                    540:                                printf("nfs_read: hit EOF unexpectantly");
                    541:                        goto ret;
                    542:                }
                    543:                fp->off += cc;
                    544:                addr += cc;
                    545:                size -= cc;
                    546:        }
                    547: ret:
                    548:        if (resid)
                    549:                *resid = size;
                    550:
                    551:        return (0);
                    552: }
                    553:
                    554: /*
                    555:  * Not implemented.
                    556:  */
                    557: int
                    558: nfs_write(struct open_file *f, void *buf, size_t size, size_t *resid)
                    559: {
                    560:        return (EROFS);
                    561: }
                    562:
                    563: off_t
                    564: nfs_seek(struct open_file *f, off_t offset, int where)
                    565: {
                    566:        struct nfs_iodesc *d = (struct nfs_iodesc *)f->f_fsdata;
                    567:        n_long size = ntohl(d->fa.fa_size);
                    568:
                    569:        switch (where) {
                    570:        case SEEK_SET:
                    571:                d->off = offset;
                    572:                break;
                    573:        case SEEK_CUR:
                    574:                d->off += offset;
                    575:                break;
                    576:        case SEEK_END:
                    577:                d->off = size - offset;
                    578:                break;
                    579:        default:
                    580:                return (-1);
                    581:        }
                    582:
                    583:        return (d->off);
                    584: }
                    585:
                    586: /* NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 */
                    587: int nfs_stat_types[8] = {
                    588:        0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, 0 };
                    589:
                    590: int
                    591: nfs_stat(struct open_file *f, struct stat *sb)
                    592: {
                    593:        struct nfs_iodesc *fp = (struct nfs_iodesc *)f->f_fsdata;
                    594:        n_long ftype, mode;
                    595:
                    596:        ftype = ntohl(fp->fa.fa_type);
                    597:        mode  = ntohl(fp->fa.fa_mode);
                    598:        mode |= nfs_stat_types[ftype & 7];
                    599:
                    600:        sb->st_mode  = mode;
                    601:        sb->st_nlink = ntohl(fp->fa.fa_nlink);
                    602:        sb->st_uid   = ntohl(fp->fa.fa_uid);
                    603:        sb->st_gid   = ntohl(fp->fa.fa_gid);
                    604:        sb->st_size  = ntohl(fp->fa.fa_size);
                    605:
                    606:        return (0);
                    607: }
                    608:
                    609: /*
                    610:  * Not implemented.
                    611:  */
                    612: #ifndef NO_READDIR
                    613: int
                    614: nfs_readdir(struct open_file *f, char *name)
                    615: {
                    616:        return (EROFS);
                    617: }
                    618: #endif

CVSweb