Annotation of coherent/b/kernel/coh.386/sys5.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * system calls introduced by the 386 port
                      3:  *
                      4:  * Copyright (c) Ciaran O'Donnell, Bievres (FRANCE), 1991
                      5:  */ 
                      6: #include <sys/coherent.h>
                      7: #include <sys/buf.h>
                      8: #include <errno.h>
                      9: #include <canon.h>
                     10: #include <sys/con.h>
                     11: #include <fcntl.h>
                     12: #include <sys/fd.h>
                     13: #include <sys/filsys.h>
                     14: #include <sys/ino.h>
                     15: #include <sys/inode.h>
                     16: #include <sys/io.h>
                     17: #include <sys/mount.h>
                     18: #include <sys/stat.h>
                     19: #include <dirent.h>
                     20: #include <sys/utsname.h>
                     21: #include <sys/mount.h>
                     22: #include <ustat.h>
                     23: #include <sys/statfs.h>
                     24: #include <sys/sysi86.h>
                     25: 
                     26: utime(tp)
                     27: long *tp;
                     28: {
                     29:        return timer.t_time;
                     30: }
                     31: 
                     32: /*
                     33:  * Return an unique number.
                     34:  */
                     35: usysi86(f, arg1)
                     36: {
                     37:        register MOUNT *mp;
                     38:        register struct filsys *fsp;
                     39:        extern void (*ndpEmFn)();
                     40:        int fpval;
                     41:        extern short ndpType;
                     42: 
                     43:        switch (f) {
                     44:        case SYI86UNEEK:
                     45:                if ((mp=getment(rootdev, 1)) == NULL)
                     46:                        return;
                     47:                fsp = &mp->m_super;
                     48:                fsp->s_fmod = 1;
                     49:                return (++fsp->s_unique);
                     50:        case SI86FPHW:
                     51:                /* 
                     52:                 * 2's bit: floating point ndp is present (80287/80387/80486dx)
                     53:                 * 1's bit (when 2's bit = 1): 80387/486dx is present
                     54:                 */
                     55:                if (!useracc(arg1, sizeof(int), 1)) {
                     56:                        SET_U_ERROR(EFAULT, "sysi386:SI86FPHW");
                     57:                        return;
                     58:                }
                     59:                if (ndpType <= 1) { /* no ndp */
                     60:                        fpval = (ndpEmFn) ? FP_SW : FP_NO;
                     61:                } else {
                     62:                        fpval = (ndpType > 2) ? FP_387 : FP_287;
                     63:                }
                     64:                putuwd(arg1, fpval);
                     65:                return 0;
                     66:                break;
                     67:        }
                     68: }
                     69: 
                     70: ushmsys(func, arg1, arg2, arg3)
                     71: int func, arg1, arg2, arg3;
                     72: {
                     73:        switch(func){
                     74:                case 0: return ushmat(arg1, arg2, arg3);
                     75:                case 1: return ushmctl(arg1, arg2, arg3);
                     76:                case 2: return ushmdt(arg1);
                     77:                case 3: return ushmget(arg1, arg2, arg3);
                     78:                default: u.u_error = EINVAL;
                     79:        }
                     80: }
                     81: 
                     82: usemsys(func, arg1, arg2, arg3, arg4)
                     83: int func, arg1, arg2, arg3, arg4;
                     84: {
                     85:        switch(func){
                     86:        case 0: return usemctl(arg1, arg2, arg3, arg4);
                     87:        case 1: return usemget(arg1, arg2, arg3);
                     88:        case 2: return usemop(arg1, arg2, arg3);
                     89:        default: u.u_error = EINVAL;
                     90:        }
                     91: }
                     92: 
                     93: /*
                     94:  * uname and ustat system calls.
                     95:  *
                     96:  * int uname(struct utsname *name)
                     97:  * Before lcall instruction 4(%esp) contains name, 8(%esp) contains
                     98:  * an unspecified value, and 12(%esp) contains the value 0.
                     99:  *
                    100:  * int ustat(int dev, struct ustat *buf)
                    101:  * Before lcall instruction 4(%esp) contains buf (REVERSE order of argument)
                    102:  * 8(%esp) contains dev, and 12(%esp) contains the value 0.
                    103:  */
                    104: int
                    105: uutssys(arg1, arg2, func)
                    106: {
                    107:        switch(func) {  
                    108:        case 0: return uname(arg1);
                    109:        case 2: return u_ustat(arg2, arg1);
                    110:        default:u.u_error = EINVAL;
                    111:        }
                    112: }
                    113: 
                    114: /*
                    115:  * uname - get name of the current operating system.
                    116:  */
                    117: extern char    version[];      /* Defined in main.c */
                    118: extern char    release[];      /* Defined in main.c */
                    119: 
                    120: /*
                    121:  * uname() should return a non-negative value on success
                    122:  * On failure, u.u_error is set.
                    123:  */
                    124: int
                    125: uname(name)
                    126: struct utsname *name;
                    127: {
                    128:        register char   *rcp;                   /**/
                    129:        register int    i;                      /* Counter, loop index */
                    130:        register INODE  *ip;                    /* /etc/uucpname inode */
                    131:        BUF             *bp;                    /* Read buffer */
                    132:        char            namebuf[SYS_NMLN];      /* System name */
                    133:        int             fl;                     /* File length*/
                    134: 
                    135:        /* Check if *name is an available user area */
                    136:        if (!useracc((char *) name, sizeof(struct utsname), 1)) {
                    137:                u.u_error = EFAULT;
                    138:                return;
                    139:        }
                    140: 
                    141:        /* Find the size of the version number */
                    142:        for (rcp = version, i = 0; *rcp != '\0' && i < SYS_NMLN; i++, rcp++)
                    143:                        ;
                    144: 
                    145:        /* Write version number to user area */
                    146:        if (!kucopy(version, name->version, i)) {
                    147:                u.u_error = EFAULT;
                    148:                return;
                    149:        }
                    150: 
                    151:        /* Find the size of the release number */
                    152:        for (rcp = release, i = 0; *rcp != '\0' && i < SYS_NMLN; i++, rcp++)
                    153:                        ;
                    154: 
                    155:        /* Write release number to user area */
                    156:        if (!kucopy(release, name->release, i)) {
                    157:                u.u_error = EFAULT;
                    158:                return;
                    159:        }
                    160: 
                    161:        /* Write "machine" to user area */
                    162:        if (!kucopy("i386", name->machine, 4)) {
                    163:                u.u_error = EFAULT;
                    164:                return;
                    165:        }
                    166: 
                    167:        /* We supposed that system name and nodename are in /etc/uucpname */
                    168:        if (ftoi("/etc/uucpname", 'r') != 0)
                    169:                return(sys_unknown(name));
                    170: 
                    171:        ip = u.u_cdiri;
                    172:        if ((fl = ip->i_size) == 0) {
                    173:                idetach(ip);
                    174:                return(sys_unknown(name));
                    175:        }
                    176: 
                    177:        /* iaccess() sets u_error if it fails. */
                    178:        if (iaccess(ip, IPR) == 0) {
                    179:                idetach(ip);
                    180:                return;
                    181:        }
                    182: 
                    183:        if ((bp = vread(ip, (daddr_t) 0)) == NULL) {
                    184:                brelease(bp);
                    185:                idetach(ip);
                    186:                u.u_error = EFAULT;
                    187:                return;
                    188:        }
                    189: 
                    190:        /* namebuf should be not more than SYS_NMLN - 1 characters long */
                    191:        fl = (fl > SYS_NMLN) ? SYS_NMLN : fl;
                    192:        kkcopy(bp->b_vaddr, namebuf, fl);
                    193:        brelease(bp);
                    194:        idetach(ip);
                    195: 
                    196:        if (fl == 1 && namebuf[0] == '\n')
                    197:                return(sys_unknown(name));
                    198: 
                    199:        for (rcp = namebuf, i = 0; i < fl; rcp++) {
                    200:                i++;
                    201:                if (*rcp == '\n') {
                    202:                        *rcp = '\0';
                    203:                        break;
                    204:                }
                    205:        }
                    206:        namebuf[i - 1] = '\0';
                    207: 
                    208:        /* Write system name to user area */
                    209:        if (!kucopy(namebuf, name->sysname, i)) {
                    210:                u.u_error = EFAULT;
                    211:                return;
                    212:        }
                    213: 
                    214:        /* Write system name to user area */
                    215:        if (!kucopy(namebuf, name->nodename, i)) {
                    216:                u.u_error = EFAULT;
                    217:                return;
                    218:        }
                    219: 
                    220:        return 0;
                    221: }
                    222: 
                    223: /*
                    224:  * sys_unknown - write name unknown to utsname struct
                    225:  * Return 0 on success.
                    226:  * Set u.u_error on failure.
                    227:  */
                    228: char   unknown[] = "UNKNOWN";
                    229: 
                    230: int
                    231: sys_unknown(name)
                    232: struct utsname *name;
                    233: {
                    234:        if (!kucopy(unknown, name->sysname, sizeof(unknown))) {
                    235:                u.u_error = EFAULT;
                    236:                return;
                    237:        }
                    238: 
                    239:        if (!kucopy(unknown, name->nodename, sizeof(unknown))) {
                    240:                u.u_error = EFAULT;
                    241:                return;
                    242:        }
                    243: 
                    244:        return 0;
                    245: }
                    246: 
                    247: /* 
                    248:  * u_ustat - get file system statistics. (Name ustat in use for stat s.c.)
                    249:  */
                    250: u_ustat(dev, buf)
                    251: dev_t  dev;
                    252: struct ustat   *buf;
                    253: {
                    254:        register MOUNT  *mp;
                    255: 
                    256:        /* Check if buf is an available user area. */
                    257:        /* B_READ | B_WRITE is not implemented yet. */
                    258:        if (!useracc((char *) buf, sizeof(struct ustat), 1)) {
                    259:                u.u_error = EFAULT;
                    260:                return;
                    261:        }
                    262: 
                    263:        /* Take mount filesystem, check if dev is mounted device */
                    264:        for (mp = mountp; mp != NULL; mp = mp->m_next)
                    265:                if (mp->m_dev == dev)
                    266:                        break;
                    267:        if (mp == NULL) {
                    268:                u.u_error = EINVAL;
                    269:                return;
                    270:        }
                    271: 
                    272:        /* Pickup information from superblock */
                    273:        /* Number of free blocks */
                    274:        if (!kucopy(&(mp->m_super.s_tfree), &(buf->f_tfree),  
                    275:                                                sizeof(mp->m_super.s_tfree)))
                    276:                return;
                    277:        /* Number of free inodes */
                    278:        if (!kucopy(&(mp->m_super.s_tinode), &(buf->f_tinode),  
                    279:                                                sizeof(mp->m_super.s_tinode)))
                    280:                return;
                    281:        /* File system name */
                    282:        if (!kucopy(mp->m_super.s_fname, buf->f_fname,  
                    283:                                                sizeof(mp->m_super.s_fname)))
                    284:                return;
                    285:        /* File system pack name */
                    286:        if (!kucopy(mp->m_super.s_fpack, buf->f_fpack,  
                    287:                                                sizeof(mp->m_super.s_fpack)))
                    288:                return;
                    289: }
                    290: 
                    291: umsgsys(func, arg1, arg2, arg3, arg4, arg5)
                    292: {
                    293:        switch (func) {
                    294:        case 0: return umsgget(arg1, arg2);
                    295:        case 1: return umsgctl(arg1, arg2, arg3);
                    296:        case 2: return umsgrcv(arg1, arg2, arg3, arg4, arg5);
                    297:        case 3: return umsgsnd(arg1, arg2, arg3, arg4);
                    298:        default:u.u_error = EINVAL;
                    299:        }
                    300: }
                    301: 
                    302: /* Don't tell user process about last remaining 64k of RAM */
                    303: #define BRK_CUSHION    16
                    304: 
                    305: uulimit(cmd, newlimit)
                    306: {
                    307:        int freeClicks;
                    308: 
                    309:        switch (cmd) {
                    310:        case 1: /* Get max # of 512-byte blocks per file. */
                    311:                return u.u_bpfmax;
                    312:                break;
                    313:        case 2: /* Set max # of 512-byte blocks per file. */
                    314:                /* (only superuser may increase this) */
                    315:                if (newlimit <= u.u_bpfmax || super()) {
                    316:                        u.u_bpfmax = newlimit;
                    317:                        return 0;
                    318:                }
                    319:                /* else super() will have set u.u_error to EPERM */
                    320:                break;
                    321:        case 3: /* Get max break value. */
                    322:                /* return (current brk value) + (amount of free space) */
                    323:                /* Don't report all free clicks - leave a cushion. */
                    324:                freeClicks = allocno() - BRK_CUSHION;
                    325:                if (freeClicks < 0)
                    326:                        freeClicks = 0;
                    327:                return u.u_segl[SIPDATA].sr_base
                    328:                  + SELF->p_segp[SIPDATA]->s_size + NBPC * freeClicks;
                    329:                break;
                    330:        case 4: /* Return configured number of open files per process. */
                    331:                return NOFILE;
                    332:                break;
                    333:        default:
                    334:                u.u_error = EINVAL;
                    335:        }
                    336: }
                    337: 
                    338: /*
                    339:  *  Change the size of a file.
                    340:  */
                    341: uchsize(fd, size)
                    342: int fd;
                    343: register long size;
                    344: {
                    345:        FD *fdp;
                    346:        register INODE *ip;
                    347: 
                    348:        if ( size < 0 ) {
                    349:                u.u_error = EINVAL;
                    350:                return -1;
                    351:        }
                    352:        if ( ((fdp=fdget(fd))==NULL) || ((fdp->f_flag&IPW)==0) ) {
                    353:                u.u_error = EBADF;
                    354:                return -1;
                    355:        }
                    356:        ip = fdp->f_ip;
                    357:        switch ( ip->i_mode&IFMT ) {
                    358:        case IFREG:
                    359:                if ( size > (((long) u.u_bpfmax) * BSIZE) ) {
                    360:                        u.u_error = EFBIG;
                    361:                        return -1;
                    362:                }
                    363:                if ( size == ip->i_size )
                    364:                        break;
                    365:                ilock(ip);
                    366:                if ( size < ip->i_size )
                    367:                        blclear(ip, (ip->i_size+BSIZE-1)/BSIZE);
                    368:                ip->i_size = size;
                    369:                imod(ip);
                    370:                icrt(ip);
                    371:                iunlock(ip);
                    372:                break;
                    373:        case IFPIPE:
                    374:                if ( size > PIPSIZE ) {
                    375:                        u.u_error = EFBIG;
                    376:                        return -1;
                    377:                }
                    378:                ilock(ip);
                    379:                if ( !ip->i_par && !ip->i_psr ) {
                    380:                        u.u_error = EPIPE;
                    381:                        sendsig(SIGPIPE, SELF);
                    382:                        iunlock(ip);
                    383:                        return -1;
                    384:                }
                    385:                ip->i_pwx += (size - ip->i_pnc);
                    386:                if ( size > ip->i_pnc ) {
                    387:                        if ( ip->i_pwx >= PIPSIZE )
                    388:                                ip->i_pwx -= PIPSIZE;
                    389:                } else if ( size < ip->i_pnc ) {
                    390:                        if ( ip->i_pwx < 0 )
                    391:                                ip->i_pwx += PIPSIZE;
                    392:                }
                    393:                ip->i_pnc = size;
                    394:                imod(ip);
                    395:                icrt(ip);
                    396:                if ( size > 0 )
                    397:                        pwake(ip, 2);   /* 2==IFWFW, see pipe.c */
                    398:                if ( size < PIPSIZE )
                    399:                        pwake(ip, 1);   /* 1==IFWFR, see pipe.c */
                    400:                iunlock(ip);
                    401:                break;
                    402:        default:
                    403:                u.u_error = EBADF;
                    404:                return -1;
                    405:        }
                    406:        return 0;
                    407: }
                    408: 
                    409: /*
                    410:  * Remove a directory.
                    411:  */
                    412: urmdir(path)
                    413: char   *path;
                    414: {
                    415:        register INODE  *ip;
                    416:        int             isdirempty();
                    417:        
                    418:        if (ftoi(path, 'r') != 0)
                    419:                return;
                    420:        ip = u.u_cdiri;
                    421: 
                    422:        /* Check if path is a directory */
                    423:        if ((ip->i_mode & IFMT) != IFDIR) {
                    424:                idetach(ip);
                    425:                SET_U_ERROR(ENOTDIR, "rmdir: no such file or directory");
                    426:                return;
                    427:        }
                    428:        /* We have to check if directory is empty */
                    429:        if (!isdirempty(ip)) {
                    430:                idetach(ip);
                    431:                SET_U_ERROR(EEXIST, "rmdir: directory is not empty");
                    432:                return;
                    433:        }
                    434:        idetach(ip);
                    435:        removedir(path);
                    436:        return (u.u_error);
                    437: }
                    438: 
                    439: /*
                    440:  * remove a directory entry.
                    441:  * path is a pointer to user area.
                    442:  */
                    443: removedir(path)
                    444: char   *path;
                    445: {
                    446:        char            buf[512];
                    447:        char            *cpbuf,         /* to internal file_name buffer */
                    448:                        *cppath;        /* to user file_name buffer */
                    449: 
                    450:        /* Write path to a kernel buffer buf */
                    451:        cpbuf = buf;
                    452:        cppath = path;
                    453: 
                    454:        while ((*cpbuf = getubd(cppath)) != '\0') {
                    455:                cppath++;
                    456:                if (++cpbuf >= &buf[sizeof(buf) - 3]) {
                    457:                        SET_U_ERROR(ENOENT, "rmdir: path too long");
                    458:                        return;
                    459:                }
                    460:        }
                    461:        *cpbuf++ = '/';
                    462:        *cpbuf++ = '.';
                    463:        *cpbuf = '\0';
                    464:        u.u_io.io_seg = IOSYS;
                    465:        dunlink(buf);
                    466:        *cpbuf++ = '.';
                    467:        *cpbuf = '\0';
                    468:        dunlink(buf);
                    469:        u.u_io.io_seg = IOUSR;
                    470:        dunlink(path);
                    471:        return;
                    472: }
                    473: 
                    474: /*
                    475:  * Unlink the given directory.
                    476:  */
                    477: dunlink(np)
                    478: char *np;
                    479: {
                    480:        register INODE *ip;
                    481:        register dev_t dev;
                    482: 
                    483:        if (ftoi(np, 'u') != 0)
                    484:                return;
                    485:  
                    486:        ip = u.u_pdiri;
                    487:        if (iaccess(ip, IPW) == 0) {
                    488:                u.u_error = EACCES;
                    489:                goto err;
                    490:        }
                    491: 
                    492:        dev = ip->i_dev;
                    493:        if (diucheck(dev, u.u_cdirn) == 0)
                    494:                goto err;
                    495:        idirent(0);
                    496:        idetach(ip);
                    497: 
                    498:        if ((ip=iattach(dev, u.u_cdirn)) == NULL)
                    499:                return;
                    500: 
                    501:        if (ip->i_nlink > 0)
                    502:                --ip->i_nlink;
                    503:        icrt(ip);       /* unlink - ctime */
                    504: 
                    505: err:
                    506:        idetach(ip);
                    507:        return (0);
                    508: }
                    509: 
                    510: /*
                    511:  * This is a copy of iucheck. The only one difference is that that allows
                    512:  * to remove a directory to a regular user.
                    513:  */
                    514: diucheck(dev, ino)
                    515: register dev_t dev;
                    516: register ino_t ino;
                    517: {
                    518:        register INODE *ip;
                    519:        INODE inode;
                    520: 
                    521:        for (ip=&inodep[NINODE-1]; ip>=inodep; --ip) {
                    522:                if (ip->i_ino==ino && ip->i_dev==dev)
                    523:                        break;
                    524:        }
                    525:        if (ip < inodep) {
                    526:                ip = &inode;
                    527:                ip->i_dev = dev;
                    528:                ip->i_ino = ino;
                    529:                if (icopydm(ip) == 0)
                    530:                        return (0);
                    531:        }
                    532:        return (1);
                    533: }
                    534: 
                    535: /* 
                    536:  * Check if directory is empty.
                    537:  */
                    538: int isdirempty(ip)
                    539: register INODE *ip;
                    540: {
                    541:        register char   *cp;
                    542:        int             count;
                    543:        BUF             *bp;
                    544: 
                    545:        for (count = 0; count < ip->i_size; count += 512) {
                    546:                if ((bp = vread(ip, count)) == NULL) 
                    547:                        break;
                    548:                for (cp = (char *) bp->b_vaddr; 
                    549:                                cp < (char *) bp->b_vaddr + BSIZE; cp += 16) {
                    550:                        if (*cp == '\0' && *(cp + 1) == '\0') 
                    551:                                continue;
                    552:                        if (*(cp + 2) != '.')
                    553:                                goto bad;
                    554:                        if (*(cp + 3) == '\0')
                    555:                                continue;
                    556:                        if (*(cp + 3) != '.' || *(cp + 4) != '\0')
                    557:                                goto bad;
                    558:                }
                    559:                brelease(bp);
                    560:        }
                    561:        return 1;
                    562: bad:
                    563:        brelease(bp);
                    564:        return 0;
                    565: }
                    566: 
                    567: /*
                    568:  * SysV compatible mkdir() system call.
                    569:  *
                    570:  *     Create a directory of the given "path" and "mode", if possible.
                    571:  *     Creating the directory is straight forward.  Trying to clean
                    572:  *     up in case we run out of inodes or freee blocks in the process 
                    573:  *     is not trivial.
                    574:  *     This system call was implemented in very press time.
                    575:  *     Vlad 6-04-92
                    576:  */
                    577: umkdir(path, mode)
                    578: char   *path;
                    579: int    mode;
                    580: {
                    581:        INODE           *dmknod();              /* make directory node */
                    582:        register INODE  *pip;                   /* parent inode pointer */
                    583:        register char   *cp_path, 
                    584:                        *cpb_path, 
                    585:                        *cp_dot, 
                    586:                        *cp_dotdot,
                    587:                        *cp_parent;
                    588:        char            bufpath[512],
                    589:                        bufdot[512],            
                    590:                        bufdotdot[512],
                    591:                        bufparent[512];
                    592:        int             uid;
                    593:        int             error;
                    594:        /*
                    595:         * Create a local copies of "path" which we can use to build up
                    596:         * the required directory links:
                    597:         *      path/. -- bufdot
                    598:         *      path/..-- bufdotdot
                    599:         * Verify that the given path is not too long.
                    600:         */
                    601:        cp_path = path;
                    602:        cpb_path = bufpath;
                    603:        cp_dot = bufdot;
                    604:        cp_dotdot = bufdotdot;
                    605:        cp_parent = bufparent;
                    606: 
                    607:        while ((*cpb_path = getubd(cp_path)) != '\0') {
                    608:                *cp_dot++ = *cp_dotdot++ = *cp_parent++ = *cpb_path;
                    609:                ++cp_path;
                    610:                if (++cpb_path >= &bufpath[sizeof(bufpath) - 3]) {
                    611:                        SET_U_ERROR(ENOENT, "sys5: mkdir: path too long");
                    612:                        return;
                    613:                }
                    614:        }
                    615:        while (--cp_parent >= bufparent) {
                    616:                if (*cp_parent == '/') {
                    617:                        *++cp_parent = '\0';
                    618:                        break;
                    619:                }
                    620:        }
                    621:        if (cp_parent < bufparent) {
                    622:                *++cp_parent = '.';
                    623:                *++cp_parent = '\0';
                    624:        }
                    625:        
                    626:        *cp_dotdot++ = *cp_dot++ = '/';
                    627:        *cp_dotdot++ = *cp_dot++ = '.';
                    628:        *cp_dotdot++ = '.';
                    629:        *cp_dotdot = *cp_dot = '\0';
                    630: 
                    631:        u.u_io.io_seg = IOSYS;
                    632: 
                    633:        u.u_io.io_seg = IOUSR;
                    634:        if ((pip = dmknod(path, mode)) == NULL) {
                    635:                return;
                    636:        }
                    637:        u.u_io.io_seg = IOSYS;
                    638:        /* Now we can switch our id to root. It allows to use existing
                    639:          * functions.
                    640:         */
                    641:        uid = u.u_uid;
                    642:        u.u_uid = 0;
                    643:        ulink(bufpath, bufdot);
                    644:        if (u.u_error) {
                    645:                error = u.u_error;
                    646:                u.u_error = 0;
                    647:                uunlink(bufpath);
                    648:                u.u_error = 0;
                    649:                u.u_io.io_seg = IOUSR;
                    650:                u.u_uid = uid;
                    651:                u.u_error = error;
                    652:                return;
                    653:        }
                    654:        ulink(bufparent, bufdotdot);
                    655:        if (u.u_error) {
                    656:                error = u.u_error;
                    657:                u.u_error = 0;
                    658:                uunlink(bufdot);
                    659:                u.u_error = 0;
                    660:                uunlink(bufpath);
                    661:                u.u_uid = uid;
                    662:                u.u_io.io_seg = IOUSR;
                    663:                u.u_error = error;
                    664:                return;
                    665:        }
                    666:        u.u_io.io_seg = IOUSR;
                    667:        u.u_uid = uid;
                    668:        return 0;
                    669: }
                    670: 
                    671: /*
                    672:  * Create a directory.
                    673:  * We cannot use original ulink because it makes the directories only for
                    674:  * superuser.
                    675:  */
                    676: INODE *dmknod(np, mode)
                    677: char   *np;    /* Direcotory name */
                    678: int    mode;
                    679: {
                    680:        register INODE *ip, *pip;
                    681:        register int type;
                    682: 
                    683:        type = (mode & ~IFMT);
                    684:        type |= S_IFDIR;
                    685: 
                    686:        if (ftoi(np, 'c') != 0)
                    687:                return NULL;
                    688: 
                    689:        if ((ip=u.u_cdiri) != NULL) {
                    690:                SET_U_ERROR(EEXIST, "sys5: path already exist")
                    691:                idetach(ip);
                    692:                return NULL;
                    693:        }
                    694:        if ((ip=imake(type, (dev_t) 0)) != NULL)
                    695:                idetach(ip);
                    696:        pip = u.u_pdiri;        /* grab ptr to parent inode */
                    697:        return pip;
                    698: }
                    699: 
                    700: /*
                    701:  * Get directory entry in file system independent format.
                    702:  */
                    703: ugetdents(fd, bp, n)
                    704: int            fd;     /* File descriptor to an open directory */
                    705: char           *bp;    /* Buffer where entries should be read */
                    706: unsigned       n;      /* Number of bytes to be read */
                    707: {
                    708:        struct direct   r_dir;  
                    709:        unsigned        bytes;  /* Number of bytes */
                    710:        struct dirent   sd;
                    711:        ino_t           inode;  /* Inode number */
                    712:        unsigned short  ofnm;   /* Offset to file name in dirent */
                    713:        char            *cw, 
                    714:                        *cr;
                    715:        int             minbuf; /* Minimum possible size of the bp */
                    716:        int             i, mod;
                    717:        int             entry;
                    718:        char            ends[3] = "";
                    719:        int             total = 0;
                    720: 
                    721:        cw = bp;
                    722: 
                    723:        ofnm = sizeof(sd.d_ino) + sizeof(sd.d_off) + sizeof(sd.d_reclen);
                    724: 
                    725:        /* Find minimum possible size of bp. It should be enough to contain the
                    726:         * header of dirent, file name + '\0', and be on a sizeof(long)
                    727:         * boundary.
                    728:         */
                    729:        entry = ofnm + DIRSIZ + 1;
                    730:        mod = entry % sizeof(long);
                    731:        minbuf = entry + (mod ? sizeof(long) - mod : 0); 
                    732: 
                    733:        /* Is user buffer available? */
                    734:        if (!useracc(bp, n, 1) || n < minbuf) {
                    735:                u.u_error = EFAULT;
                    736:                return(0);
                    737:        }
                    738: 
                    739:        while(n - (cw - bp) >= minbuf) {
                    740:                /* Read next entry from the directory. 
                    741:                 * inode == 0 for rm(ed) entries 
                    742:                 */
                    743:                do {
                    744:                        if ((bytes = dirio(fd, &r_dir, sizeof(struct direct), 
                    745:                                                        &sd.d_off)) == 0) {
                    746:                                return(total);
                    747:                        }
                    748:                        inode = r_dir.d_ino;
                    749:                } while (!inode);
                    750: 
                    751:                /* Find the size of file name */
                    752:                for (cr = r_dir.d_name, i = 0; *cr != '\0' && i < DIRSIZ; 
                    753:                                                i++, cr++)
                    754:                        ;
                    755: 
                    756:                /* Copy file name */
                    757:                if (!kucopy(r_dir.d_name, cw + ofnm, i))
                    758:                        return(0);
                    759:                /* Write '\0' */
                    760:                putubd(cw + ofnm + i++, '\0');
                    761:                /* Round up to long boundary */
                    762:                if (mod = (ofnm + i) % sizeof(long))
                    763:                        if (!kucopy(ends, cw + ofnm + i, sizeof(long) - mod))
                    764:                                return(0);
                    765:                sd.d_ino = r_dir.d_ino;
                    766:                sd.d_reclen = ofnm + i;         /* Size of directory entry */
                    767:                if (mod)
                    768:                        sd.d_reclen += sizeof(long) - mod;
                    769:                if (!kucopy(&sd, cw, ofnm))
                    770:                        return(0);
                    771:                total += sd.d_reclen;
                    772:                cw += sd.d_reclen;
                    773:        }
                    774:        return(total);
                    775: }
                    776: 
                    777: /*
                    778:  * Read `n' bytes from the directory `fd' using the buffer `bp'.
                    779:  */
                    780: dirio(fd, bp, n, offset)
                    781: struct direct  *bp;
                    782: unsigned       n;
                    783: off_t          *offset;
                    784: {
                    785:        register FD *fdp;
                    786:        register INODE *ip;
                    787: 
                    788:        /* Check file descriptor */
                    789:        if ((fdp = fdget(fd)) == NULL)
                    790:                return (0);
                    791:        if (((fdp->f_flag & IPR)) == 0) {
                    792:                u.u_error = EBADF;
                    793:                return (0);
                    794:        }
                    795:        ip = fdp->f_ip;
                    796:        if ((ip->i_mode & IFMT) != IFDIR) {
                    797:                u.u_error = EBADF;
                    798:                return(0);
                    799:        }
                    800: 
                    801:        ilock(ip);      /* We do not want file changes during the read */
                    802: 
                    803:        u.u_io.io_seek = fdp->f_seek;
                    804:        u.u_io.io.vbase = bp;
                    805:        u.u_io.io_ioc  = n;
                    806:        u.u_io.io_flag = (fdp->f_flag & IPNDLY) ? IONDLY : 0;
                    807: 
                    808:        iread(ip, &u.u_io);
                    809:        iacc(ip);               /* read - atime */
                    810: 
                    811:        n -= u.u_io.io_ioc;
                    812:        *offset = fdp->f_seek;
                    813:        fdp->f_seek += n;
                    814: 
                    815:        iunlock(ip);
                    816: 
                    817:        return (n);
                    818: }
                    819: 
                    820: /* 
                    821:  * Get file system information by file name.
                    822:  */
                    823: ustatfs(path, stfs, len, fstyp)
                    824: char           *path;  /* File name */
                    825: struct statfs  *stfs;  /* Pointer to a user structure */
                    826: int            len;    /* Size of the structure */
                    827: int            fstyp;  /* File system type */
                    828: {
                    829:        struct filsys   *statmount();   /* Get mp for mounted device */
                    830:        struct filsys   *statunmount(); /* Get mp for unmounted device */
                    831:        struct filsys   *sb;            /* Pointer to superblock */
                    832:        int             count = 0;      /* Number of copied bytes */
                    833:        short           systype = 1;    /* System type */
                    834:        long            bsize = BSIZE;  /* Block size */
                    835:        long            frsize = 0;     /* Fragment size */
                    836: 
                    837:        /* Check if stfs is an available user area. */
                    838:        if (!useracc((char *) stfs, len, 1)) {
                    839:                SET_U_ERROR(EFAULT, "ustatfs 0");
                    840:                return;
                    841:        }
                    842: 
                    843:        /* Filesystem type is 1 for 512 bytes blocks. */
                    844:        count += sizeof(systype);
                    845:        if (count > len) {
                    846:                SET_U_ERROR(EFAULT, "ustatfs 1");
                    847:                return;
                    848:        }
                    849:        if (!kucopy(&(systype), &(stfs->f_fstyp), sizeof(systype)))
                    850:                return;
                    851:        
                    852:        /* Block size */
                    853:        count += sizeof(bsize);
                    854:        if (count > len) {
                    855:                SET_U_ERROR(EFAULT, "ustatfs 2");
                    856:                return;
                    857:        }
                    858:        if (!kucopy(&(bsize), &(stfs->f_bsize), sizeof(bsize)))
                    859:                return;
                    860: 
                    861:        /* Fragment size. */
                    862:        count += sizeof(int);
                    863:        if (count > len) {
                    864:                SET_U_ERROR(EFAULT, "ustatfs 3");
                    865:                return;
                    866:        }
                    867:        if (!kucopy(&(frsize), &(stfs->f_frsize), sizeof(frsize)))
                    868:                return;
                    869: 
                    870:        if (!fstyp) {
                    871:                if ((sb = statmount(-1, path)) == NULL)
                    872:                        return;
                    873:                devinfo(sb, stfs, len, &count);
                    874:        } else {
                    875:                if ((sb = statunmount(-1, path)) == NULL)
                    876:                        return;
                    877:                devinfo(sb, stfs, len, &count);
                    878:                kfree(sb);
                    879:        }
                    880:        return 0;
                    881: }
                    882: 
                    883: /*
                    884:  * statmount - get superblock for mounted file system.
                    885:  * fd - file descriptor or -1, path -  file name or NULL.
                    886:  */
                    887: struct filsys *statmount(fd, path)
                    888: int    fd;
                    889: char   *path;
                    890: {      
                    891:        register INODE  *ip;            /* Structure inode */
                    892:        register FD     *fdp;
                    893:        register MOUNT  *mp;            /* Pointer to device */
                    894:        dev_t           device;         /* Mounted device */
                    895: 
                    896:        /* Find the device */
                    897:        if (path) {     /* Find ip by file name */
                    898:                if (ftoi(path, 'r')) {
                    899:                        /* If ftoi returned nonzero, it also set u.u_error. */
                    900:                        return NULL;
                    901:                }
                    902:                ip = u.u_cdiri;
                    903:                device = ip->i_dev;
                    904:                idetach(ip);
                    905:        } else {                /* Find ip by file descriptor */
                    906:                if ((fdp = fdget(fd)) == NULL)
                    907:                        return NULL;
                    908:                if (((fdp->f_flag & IPR)) == 0) {
                    909:                        SET_U_ERROR(EBADF, "statmount 1");
                    910:                        return NULL;
                    911:                }
                    912:                ip = fdp->f_ip;
                    913:                device = ip->i_dev;
                    914:        }       
                    915:        /* Take mount filesystem, check if dev is mounted device */
                    916:        for (mp = mountp; mp != NULL; mp = mp->m_next)
                    917:                if (mp->m_dev == device)
                    918:                        break;
                    919:        if (mp == NULL) {
                    920:                u.u_error = EINVAL;
                    921:                return NULL;
                    922:        }
                    923:        return &mp->m_super;
                    924: }
                    925: 
                    926: /*
                    927:  * devinfo() write system information to user area
                    928:  */
                    929: devinfo(sb, stfs, len, count)
                    930: struct filsys  *sb;    /* File name */
                    931: struct statfs  *stfs;  /* Pointer to a user structure */
                    932: int            len;    /* Size of the structure */
                    933: int            *count;
                    934: {
                    935:        long            inode;
                    936: 
                    937:        /* Total number of blocks */
                    938:        *count += sizeof(sb->s_fsize);
                    939:        if (*count > len)
                    940:                return;
                    941:        if (!kucopy(&(sb->s_fsize), &(stfs->f_blocks), 
                    942:                                        sizeof(sb->s_fsize)))
                    943:                return;
                    944: 
                    945:        /* Count of free blocks */
                    946:        *count += sizeof(sb->s_tfree);
                    947:        if (*count > len)
                    948:                return;
                    949:        if (!kucopy(&(sb->s_tfree), &(stfs->f_bfree),
                    950:                                        sizeof(sb->s_tfree)))
                    951:                return;
                    952: 
                    953:        /* Total number of file inodes */
                    954:        *count += sizeof(inode);
                    955:        if (*count > len)
                    956:                return;
                    957:        inode = (long) (sb->s_isize - INODEI) * INOPB;
                    958:        if (!kucopy(&inode, &(stfs->f_files), sizeof(inode)))
                    959:                return;
                    960: 
                    961:        /* Number of free inodes */
                    962:        *count += sizeof(inode);
                    963:        if (*count > len)
                    964:                return;
                    965:        inode = sb->s_tinode;
                    966:        if (!kucopy(&inode, &(stfs->f_ffree), sizeof(inode)))
                    967:                return;
                    968: 
                    969:        /* Volume name */
                    970:        *count += sizeof(sb->s_fname);
                    971:        if (*count > len)
                    972:                return;
                    973:        if (!kucopy(sb->s_fname, stfs->f_fname, 
                    974:                                        sizeof(sb->s_fpack)))
                    975:                return;
                    976: 
                    977:        /* Pack name */
                    978:        *count += sizeof(sb->s_fpack);
                    979:        if (*count > len)
                    980:                return;
                    981:        if (!kucopy(sb->s_fpack, stfs->f_fpack, 
                    982:                                        sizeof(sb->s_fpack)))
                    983:                return;
                    984: }
                    985: 
                    986: /*
                    987:  * statunmount - get superblock for unmounted file system.
                    988:  * fd - file descriptor or -1, path -  file name or NULL.
                    989:  */
                    990: struct filsys *statunmount(fd, path)
                    991: int    fd;     /* File descriptor */
                    992: char   *path;  /* File name */
                    993: {
                    994:        register INODE  *ip;
                    995:        register MOUNT  *mp;
                    996:        register dev_t  rdev;
                    997:        FD              *fdp;
                    998:        int             mode;
                    999:        BUF             *bp;
                   1000:        struct filsys   *sb;
                   1001: 
                   1002:        /* Find the device */
                   1003:        if (path) {     /* Find ip by file name */
                   1004:                if (ftoi(path, 'r')) 
                   1005:                        return NULL;
                   1006:                ip = u.u_cdiri;
                   1007:                mode = ip->i_mode;
                   1008:                rdev = ip->i_a.i_rdev;
                   1009:                idetach(ip);
                   1010:        } else {                /* Find ip by file descriptor */
                   1011:                if ((fdp = fdget(fd)) == NULL)
                   1012:                        return NULL;
                   1013:                if (((fdp->f_flag & IPR)) == 0) {
                   1014:                        u.u_error = EBADF;
                   1015:                        return NULL;
                   1016:                }
                   1017:                ip = fdp->f_ip;
                   1018:                ilock(ip);
                   1019:                mode = ip->i_mode;
                   1020:                rdev = ip->i_a.i_rdev;
                   1021:                iunlock(ip);
                   1022:        }       
                   1023: 
                   1024:        /* Check for block special device */
                   1025:        if ((mode & IFMT) != IFBLK) {
                   1026:                u.u_error = ENOTBLK;
                   1027:                return NULL;
                   1028:        }
                   1029: 
                   1030:        /* Check if device is mounted device */
                   1031:        for (mp = mountp; mp != NULL; mp = mp->m_next) {
                   1032:                if (mp->m_dev == rdev) {
                   1033:                        u.u_error = EBUSY;
                   1034:                        return NULL;
                   1035:                }
                   1036:        }
                   1037:        dopen(rdev, IPR, DFBLK);
                   1038:        if (u.u_error) 
                   1039:                return NULL;
                   1040:        
                   1041:        /*
                   1042:         * NIGEL: Modified for new dclose ().
                   1043:         */
                   1044: 
                   1045:        bp = bread(rdev, (daddr_t) SUPERI, 1);
                   1046:        dclose (rdev, IPR, DFBLK);
                   1047: 
                   1048:        if (bp == NULL)
                   1049:                return NULL;
                   1050: 
                   1051:        if ((sb = kalloc(sizeof(struct filsys))) == NULL)
                   1052:                return (NULL);
                   1053: 
                   1054:        kkcopy(bp->b_vaddr, sb, sizeof(struct filsys));
                   1055:        brelease(bp);
                   1056:        cansuper(sb);           /* canonicalize supperblock */
                   1057:        if (tstf(sb) == 0) {    /* check for consistency */
                   1058:                kfree(sb);
                   1059:                u.u_error = EINVAL;
                   1060:                return(NULL);
                   1061:        }
                   1062:        return(sb);
                   1063: }
                   1064: 
                   1065: /* 
                   1066:  * Get file system information by file descriptor
                   1067:  */
                   1068: ufstatfs(fildes, stfs, len, fstyp)
                   1069: int            fildes; /* File descriptor */
                   1070: struct statfs  *stfs;  /* Pointer to a user structure */
                   1071: int            len;    /* Size of the structure */
                   1072: int            fstyp;  /* File system type */
                   1073: {      
                   1074:        struct filsys   *statmount();   /* Get mp for mounted device */
                   1075:        struct filsys   *statunmount(); /* Get mp for unmounted device */
                   1076:        struct filsys   *sb;            /* Pointer to superblock */
                   1077:        int             count = 0;      /* Number of copied bytes */
                   1078:        short           systype = 1;    /* System type */
                   1079:        long            bsize = BSIZE;  /* Block size */
                   1080:        long            frsize = 0;     /* Fragment size */
                   1081: 
                   1082:        /* Check if stfs is an available user area. */
                   1083:        if (!useracc((char *) stfs, len)) {
                   1084:                u.u_error = EFAULT;
                   1085:                return;
                   1086:        }
                   1087: 
                   1088:        /* Filesystem type is 1 for 512 bytes blocks. */
                   1089:        count += sizeof(systype);
                   1090:        if (count > len) {
                   1091:                SET_U_ERROR(EFAULT, "ufstatfs 0");
                   1092:                return;
                   1093:        }
                   1094:        if (!kucopy(&(systype), &(stfs->f_fstyp), sizeof(systype)))
                   1095:                return;
                   1096:        
                   1097:        /* Block size */
                   1098:        count += sizeof(bsize);
                   1099:        if (count > len) {
                   1100:                SET_U_ERROR(EFAULT, "ufstatfs 1");
                   1101:                return;
                   1102:        }
                   1103:        if (!kucopy(&(bsize), &(stfs->f_bsize), sizeof(bsize)))
                   1104:                return;
                   1105: 
                   1106:        /* Fragment size. */
                   1107:        count += sizeof(int);
                   1108:        if (count > len) {
                   1109:                SET_U_ERROR(EFAULT, "ufstatfs 2");
                   1110:                return;
                   1111:        }
                   1112:        if (!kucopy(&(frsize), &(stfs->f_frsize), sizeof(frsize)))
                   1113:                return;
                   1114: 
                   1115:        if (!fstyp) {
                   1116:                if ((sb = statmount(fildes, NULL)) == NULL)
                   1117:                        return;
                   1118:                devinfo(sb, stfs, len, &count);
                   1119:        } else {
                   1120:                if ((sb = statunmount(fildes, NULL)) == NULL)
                   1121:                        return;
                   1122:                devinfo(sb, stfs, len, &count);
                   1123:                kfree(sb);
                   1124:        }
                   1125:        return 0;
                   1126: }
                   1127: 
                   1128: /*
                   1129:  * Check superblock for consistency.
                   1130:  */
                   1131: tstf(fp)
                   1132: register struct filsys *fp;
                   1133: {
                   1134:        register daddr_t *dp;
                   1135:        register ino_t *ip;
                   1136:        register ino_t maxinode;
                   1137: 
                   1138:        maxinode = (fp->s_isize - INODEI) * INOPB + 1;
                   1139:        if (fp->s_isize >= fp->s_fsize)
                   1140:                return (0);
                   1141:        if (fp->s_tfree < fp->s_nfree
                   1142:         || fp->s_tfree >= fp->s_fsize - fp->s_isize + 1)
                   1143:                return (0);
                   1144:        if (fp->s_tinode < fp->s_ninode
                   1145:         || fp->s_tinode >= maxinode-1)
                   1146:                return (0);
                   1147:        for (dp = &fp->s_free[0]; dp < &fp->s_free[fp->s_nfree]; dp += 1)
                   1148:                if (*dp < fp->s_isize || *dp >= fp->s_fsize)
                   1149:                        return (0);
                   1150:        for (ip = &fp->s_inode[0]; ip < &fp->s_inode[fp->s_ninode]; ip += 1)
                   1151:                if (*ip < 1 || *ip > maxinode)
                   1152:                        return (0);
                   1153:        return (1);
                   1154: }
                   1155: 
                   1156: /* the following calls are not in the BCS */
                   1157: 
                   1158: uadmin()
                   1159: {
                   1160:        u.u_error = EINVAL;
                   1161: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.