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

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

unix.superglobalmegacorp.com

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