Annotation of coherent/b/kernel/coh.386/sys5.c, revision 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.