Annotation of coherent/d/PS2_KERNEL/coh.386/sys5.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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