[BACK]Return to ufs.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / lib / libsa

Annotation of src/sys/lib/libsa/ufs.c, Revision 1.35.2.3

1.35.2.3! skrll       1: /*     $NetBSD: ufs.c,v 1.35.2.1 2004/08/03 10:53:54 skrll Exp $       */
1.8       cgd         2:
1.1       brezak      3: /*-
                      4:  * Copyright (c) 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to Berkeley by
                      8:  * The Mach Operating System project at Carnegie-Mellon University.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
1.35.2.1  skrll      18:  * 3. Neither the name of the University nor the names of its contributors
1.1       brezak     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
1.22      simonb     33:  *
1.1       brezak     34:  *
                     35:  * Copyright (c) 1990, 1991 Carnegie Mellon University
                     36:  * All Rights Reserved.
                     37:  *
                     38:  * Author: David Golub
1.22      simonb     39:  *
1.1       brezak     40:  * Permission to use, copy, modify and distribute this software and its
                     41:  * documentation is hereby granted, provided that both the copyright
                     42:  * notice and this permission notice appear in all copies of the
                     43:  * software, derivative works or modified versions, and any portions
                     44:  * thereof, and that both notices appear in supporting documentation.
1.22      simonb     45:  *
1.1       brezak     46:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     47:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     48:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1.22      simonb     49:  *
1.1       brezak     50:  * Carnegie Mellon requests users of this software to return to
1.22      simonb     51:  *
1.1       brezak     52:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     53:  *  School of Computer Science
                     54:  *  Carnegie Mellon University
                     55:  *  Pittsburgh PA 15213-3890
1.22      simonb     56:  *
1.1       brezak     57:  * any improvements or extensions that they make and grant Carnegie the
                     58:  * rights to redistribute these changes.
1.27      cgd        59:  */
                     60:
                     61: /*
1.35.2.1  skrll      62:  *     Stand-alone file reading package for UFS and LFS filesystems.
1.1       brezak     63:  */
                     64:
                     65: #include <sys/param.h>
                     66: #include <sys/time.h>
                     67: #include <ufs/ufs/dinode.h>
                     68: #include <ufs/ufs/dir.h>
1.35      dsl        69: #ifdef LIBSA_LFS
                     70: #include <sys/queue.h>
                     71: #include <sys/mount.h>                 /* XXX for MNAMELEN */
                     72: #include <ufs/lfs/lfs.h>
                     73: #else
1.20      ross       74: #include <ufs/ffs/fs.h>
1.35      dsl        75: #endif
1.29      thorpej    76: #ifdef _STANDALONE
                     77: #include <lib/libkern/libkern.h>
                     78: #else
                     79: #include <string.h>
                     80: #endif
1.2       glass      81:
1.1       brezak     82: #include "stand.h"
1.35      dsl        83: #ifdef LIBSA_LFS
                     84: #include "lfs.h"
                     85: #else
1.21      pk         86: #include "ufs.h"
1.35      dsl        87: #endif
                     88:
                     89: /* If this file is compiled by itself, build ufs (aka ffsv1) support */
                     90: #if !defined(LIBSA_FFSv2) && !defined(LIBSA_LFS)
                     91: #define LIBSA_FFSv1
                     92: #endif
1.23      cgd        93:
                     94: #if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
                     95: #define LIBSA_NO_FS_SYMLINK
1.25      simonb     96: #endif
                     97: #if defined(COMPAT_UFS) && defined(LIBSA_NO_COMPAT_UFS)
                     98: #undef COMPAT_UFS
1.23      cgd        99: #endif
                    100:
1.35      dsl       101: #ifdef LIBSA_LFS
                    102: /*
                    103:  * In-core LFS superblock.  This exists only to placate the macros in lfs.h,
                    104:  */
                    105: struct fs {
                    106:        struct dlfs     lfs_dlfs;
1.33      fvdl      107: };
1.35      dsl       108: #define fs_magic       lfs_magic
                    109: #define fs_maxsymlinklen lfs_maxsymlinklen
1.33      fvdl      110:
1.35      dsl       111: #define FS_MAGIC       LFS_MAGIC
                    112: #define SBLOCKSIZE     LFS_SBPAD
                    113: #define SBLOCKOFFSET   LFS_LABELPAD
1.33      fvdl      114: #else
1.35      dsl       115: /* NB ufs2 doesn't use the common suberblock code... */
                    116: #define FS_MAGIC       FS_UFS1_MAGIC
                    117: #define SBLOCKOFFSET   SBLOCK_UFS1
                    118: #endif
                    119:
                    120: #if defined(LIBSA_NO_TWIDDLE)
                    121: #define twiddle()
                    122: #endif
                    123:
1.35.2.1  skrll     124: #undef cgstart
                    125: #if defined(LIBSA_FFSv2)
                    126: #define cgstart(fc, c) cgstart_ufs2((fs), (c))
                    127: #else
                    128: #define cgstart(fc, c) cgstart_ufs1((fs), (c))
                    129: #endif
                    130:
1.35      dsl       131: #ifndef ufs_dinode
                    132: #define ufs_dinode     ufs1_dinode
                    133: #endif
                    134: #ifndef indp_t
                    135: #define indp_t         uint32_t
                    136: #endif
                    137: #ifndef FSBTODB
1.35.2.1  skrll     138: #define FSBTODB(fs, indp) fsbtodb(fs, indp)
1.33      fvdl      139: #endif
1.23      cgd       140:
1.1       brezak    141: /*
1.35.2.1  skrll     142:  * To avoid having a lot of filesystem-block sized buffers lurking (which
                    143:  * could be 32k) we only keep a few entries of the indirect block map.
                    144:  * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
                    145:  * ~13 times pulling in a 6M kernel.
                    146:  * The cache size must be smaller than the smallest filesystem block,
                    147:  * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
                    148:  */
                    149: #define LN2_IND_CACHE_SZ       6
                    150: #define IND_CACHE_SZ           (1 << LN2_IND_CACHE_SZ)
                    151: #define IND_CACHE_MASK         (IND_CACHE_SZ - 1)
                    152:
                    153: /*
1.1       brezak    154:  * In-core open file.
                    155:  */
                    156: struct file {
                    157:        off_t           f_seekp;        /* seek pointer */
                    158:        struct fs       *f_fs;          /* pointer to super-block */
1.35      dsl       159:        struct ufs_dinode       f_di;           /* copy of on-disk inode */
1.35.2.1  skrll     160:        uint            f_nishift;      /* for blocks in indirect block */
                    161:        indp_t          f_ind_cache_block;
                    162:        indp_t          f_ind_cache[IND_CACHE_SZ];
                    163:
1.1       brezak    164:        char            *f_buf;         /* buffer for data block */
1.13      cgd       165:        size_t          f_buf_size;     /* size of data block */
1.1       brezak    166:        daddr_t         f_buf_blkno;    /* block number of data block */
                    167: };
                    168:
1.35.2.1  skrll     169: static int read_inode(ino_t, struct open_file *);
                    170: static int block_map(struct open_file *, indp_t, indp_t *);
                    171: static int buf_read_file(struct open_file *, char **, size_t *);
                    172: static int search_directory(const char *, int, struct open_file *, ino_t *);
1.35      dsl       173: #ifdef LIBSA_FFSv1
1.35.2.1  skrll     174: static void ffs_oldfscompat(struct fs *);
1.35      dsl       175: #endif
                    176: #ifdef LIBSA_FFSv2
1.35.2.1  skrll     177: static int ffs_find_superblock(struct open_file *, struct fs *);
1.35      dsl       178: #endif
                    179:
                    180: #ifdef LIBSA_LFS
                    181: /*
                    182:  * Find an inode's block.  Look it up in the ifile.  Whee!
                    183:  */
                    184: static int
                    185: find_inode_sector(ino_t inumber, struct open_file *f, daddr_t *isp)
                    186: {
                    187:        struct file *fp = (struct file *)f->f_fsdata;
                    188:        struct fs *fs = fp->f_fs;
                    189:        daddr_t ifileent_blkno;
                    190:        char *ent_in_buf;
                    191:        size_t buf_after_ent;
                    192:        int rc;
1.33      fvdl      193:
1.35      dsl       194:        rc = read_inode(fs->lfs_ifile, f);
                    195:        if (rc)
                    196:                return (rc);
                    197:
                    198:        ifileent_blkno =
                    199:            (inumber / fs->lfs_ifpb) + fs->lfs_cleansz + fs->lfs_segtabsz;
                    200:        fp->f_seekp = (off_t)ifileent_blkno * fs->fs_bsize +
                    201:            (inumber % fs->lfs_ifpb) * sizeof (IFILE_Vx);
                    202:        rc = buf_read_file(f, &ent_in_buf, &buf_after_ent);
                    203:        if (rc)
                    204:                return (rc);
                    205:        /* make sure something's not badly wrong, but don't panic. */
                    206:        if (buf_after_ent < sizeof (IFILE_Vx))
                    207:                return (EINVAL);
                    208:
                    209:        *isp = FSBTODB(fs, ((IFILE_Vx *)ent_in_buf)->if_daddr);
                    210:        if (*isp == LFS_UNUSED_DADDR)   /* again, something badly wrong */
                    211:                return (EINVAL);
                    212:        return (0);
                    213: }
1.7       brezak    214: #endif
                    215:
1.1       brezak    216: /*
                    217:  * Read a new inode into a file structure.
                    218:  */
                    219: static int
1.35.2.1  skrll     220: read_inode(ino_t inumber, struct open_file *f)
1.1       brezak    221: {
1.30      augustss  222:        struct file *fp = (struct file *)f->f_fsdata;
                    223:        struct fs *fs = fp->f_fs;
1.1       brezak    224:        char *buf;
1.35.2.1  skrll     225:        ssize_t rsize;
1.1       brezak    226:        int rc;
1.35      dsl       227:        daddr_t inode_sector;
                    228: #ifdef LIBSA_LFS
                    229:        struct ufs_dinode *dip;
                    230:        int cnt;
                    231: #endif
                    232:
                    233: #ifdef LIBSA_LFS
                    234:        if (inumber == fs->lfs_ifile)
                    235:                inode_sector = FSBTODB(fs, fs->lfs_idaddr);
                    236:        else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0)
                    237:                return (rc);
                    238: #else
                    239:        inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
                    240: #endif
1.1       brezak    241:
                    242:        /*
                    243:         * Read inode and save it.
                    244:         */
1.35.2.1  skrll     245:        buf = fp->f_buf;
1.11      mycroft   246:        twiddle();
1.23      cgd       247:        rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.35.2.1  skrll     248:            inode_sector, fs->fs_bsize, buf, &rsize);
1.1       brezak    249:        if (rc)
1.35.2.1  skrll     250:                return rc;
                    251:        if (rsize != (ssize_t)fs->fs_bsize)
                    252:                return EIO;
1.1       brezak    253:
1.35      dsl       254: #ifdef LIBSA_LFS
                    255:        cnt = INOPBx(fs);
1.35.2.1  skrll     256:        dip = (struct ufs_dinode *)buf + (cnt - 1);
                    257:        for (; dip->di_inumber != inumber; --dip) {
                    258:                /* kernel code panics, but boot blocks which panic are Bad. */
                    259:                if (--cnt == 0)
                    260:                        return EINVAL;
1.1       brezak    261:        }
1.35      dsl       262:        fp->f_di = *dip;
                    263: #else
                    264:        fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)];
                    265: #endif
1.1       brezak    266:
                    267:        /*
                    268:         * Clear out the old buffers
                    269:         */
1.35.2.1  skrll     270:        fp->f_ind_cache_block = ~0;
                    271:        fp->f_buf_blkno = -1;
1.22      simonb    272:        return (rc);
1.1       brezak    273: }
                    274:
                    275: /*
                    276:  * Given an offset in a file, find the disk block number that
                    277:  * contains that block.
                    278:  */
                    279: static int
1.35.2.1  skrll     280: block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
1.1       brezak    281: {
1.30      augustss  282:        struct file *fp = (struct file *)f->f_fsdata;
                    283:        struct fs *fs = fp->f_fs;
1.35.2.1  skrll     284:        unsigned level;
                    285:        indp_t ind_cache;
                    286:        indp_t ind_block_num;
                    287:        ssize_t rsize;
1.1       brezak    288:        int rc;
1.35.2.1  skrll     289:        indp_t *buf = (void *)fp->f_buf;
1.1       brezak    290:
                    291:        /*
                    292:         * Index structure of an inode:
                    293:         *
                    294:         * di_db[0..NDADDR-1]   hold block numbers for blocks
                    295:         *                      0..NDADDR-1
                    296:         *
                    297:         * di_ib[0]             index block 0 is the single indirect block
                    298:         *                      holds block numbers for blocks
                    299:         *                      NDADDR .. NDADDR + NINDIR(fs)-1
                    300:         *
                    301:         * di_ib[1]             index block 1 is the double indirect block
                    302:         *                      holds block numbers for INDEX blocks for blocks
                    303:         *                      NDADDR + NINDIR(fs) ..
                    304:         *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
                    305:         *
                    306:         * di_ib[2]             index block 2 is the triple indirect block
                    307:         *                      holds block numbers for double-indirect
                    308:         *                      blocks for blocks
                    309:         *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
                    310:         *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2
                    311:         *                              + NINDIR(fs)**3 - 1
                    312:         */
                    313:
                    314:        if (file_block < NDADDR) {
                    315:                /* Direct block. */
1.35      dsl       316:                *disk_block_p = fp->f_di.di_db[file_block];
1.1       brezak    317:                return (0);
                    318:        }
                    319:
                    320:        file_block -= NDADDR;
                    321:
1.35.2.1  skrll     322:        ind_cache = file_block >> LN2_IND_CACHE_SZ;
                    323:        if (ind_cache == fp->f_ind_cache_block) {
                    324:                *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK];
                    325:                return 0;
1.1       brezak    326:        }
1.35.2.1  skrll     327:
                    328:        for (level = 0;;) {
                    329:                level += fp->f_nishift;
                    330:                if (file_block < (indp_t)1 << level)
                    331:                        break;
                    332:                if (level > NIADDR * fp->f_nishift)
                    333:                        /* Block number too high */
                    334:                        return (EFBIG);
                    335:                file_block -= (indp_t)1 << level;
1.1       brezak    336:        }
                    337:
1.35.2.1  skrll     338:        ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1];
1.1       brezak    339:
1.35.2.1  skrll     340:        for (;;) {
                    341:                level -= fp->f_nishift;
1.1       brezak    342:                if (ind_block_num == 0) {
                    343:                        *disk_block_p = 0;      /* missing */
                    344:                        return (0);
                    345:                }
                    346:
1.35.2.1  skrll     347:                twiddle();
                    348:                /*
                    349:                 * If we were feeling brave, we could work out the number
                    350:                 * of the disk sector and read a single disk sector instead
                    351:                 * of a filesystem block.
                    352:                 * However we don't do this very often anyway...
                    353:                 */
                    354:                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
                    355:                        FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize,
                    356:                        buf, &rsize);
                    357:                if (rc)
                    358:                        return (rc);
                    359:                if (rsize != (ssize_t)fs->fs_bsize)
                    360:                        return EIO;
                    361:                ind_block_num = buf[file_block >> level];
                    362:                if (level == 0)
                    363:                        break;
                    364:                file_block &= (1 << level) - 1;
1.1       brezak    365:        }
                    366:
1.35.2.1  skrll     367:        /* Save the part of the block that contains this sector */
                    368:        memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
                    369:            IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
                    370:        fp->f_ind_cache_block = ind_cache;
                    371:
1.1       brezak    372:        *disk_block_p = ind_block_num;
                    373:
                    374:        return (0);
                    375: }
                    376:
                    377: /*
1.35.2.1  skrll     378:  * Read a portion of a file into an internal buffer.
                    379:  * Return the location in the buffer and the amount in the buffer.
1.1       brezak    380:  */
                    381: static int
1.35.2.1  skrll     382: buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
1.1       brezak    383: {
1.30      augustss  384:        struct file *fp = (struct file *)f->f_fsdata;
                    385:        struct fs *fs = fp->f_fs;
1.1       brezak    386:        long off;
1.35.2.1  skrll     387:        indp_t file_block;
                    388:        indp_t disk_block;
1.13      cgd       389:        size_t block_size;
1.1       brezak    390:        int rc;
                    391:
                    392:        off = blkoff(fs, fp->f_seekp);
                    393:        file_block = lblkno(fs, fp->f_seekp);
1.35      dsl       394: #ifdef LIBSA_LFS
                    395:        block_size = dblksize(fs, &fp->f_di, file_block);
                    396: #else
1.35.2.1  skrll     397:        block_size = sblksize(fs, (int64_t)fp->f_di.di_size, file_block);
1.35      dsl       398: #endif
1.1       brezak    399:
                    400:        if (file_block != fp->f_buf_blkno) {
                    401:                rc = block_map(f, file_block, &disk_block);
                    402:                if (rc)
                    403:                        return (rc);
                    404:
                    405:                if (disk_block == 0) {
1.35.2.1  skrll     406:                        memset(fp->f_buf, 0, block_size);
1.1       brezak    407:                        fp->f_buf_size = block_size;
                    408:                } else {
1.11      mycroft   409:                        twiddle();
1.23      cgd       410:                        rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.35      dsl       411:                                FSBTODB(fs, disk_block),
1.1       brezak    412:                                block_size, fp->f_buf, &fp->f_buf_size);
                    413:                        if (rc)
                    414:                                return (rc);
                    415:                }
                    416:
                    417:                fp->f_buf_blkno = file_block;
                    418:        }
                    419:
                    420:        /*
                    421:         * Return address of byte in buffer corresponding to
                    422:         * offset, and size of remainder of buffer after that
                    423:         * byte.
                    424:         */
                    425:        *buf_p = fp->f_buf + off;
                    426:        *size_p = block_size - off;
                    427:
                    428:        /*
                    429:         * But truncate buffer at end of file.
                    430:         */
1.35      dsl       431:        if (*size_p > fp->f_di.di_size - fp->f_seekp)
                    432:                *size_p = fp->f_di.di_size - fp->f_seekp;
1.1       brezak    433:
                    434:        return (0);
                    435: }
                    436:
                    437: /*
                    438:  * Search a directory for a name and return its
1.35.2.1  skrll     439:  * inode number.
1.1       brezak    440:  */
                    441: static int
1.35.2.1  skrll     442: search_directory(const char *name, int length, struct open_file *f,
                    443:     ino_t *inumber_p)
1.1       brezak    444: {
1.30      augustss  445:        struct file *fp = (struct file *)f->f_fsdata;
                    446:        struct direct *dp;
1.1       brezak    447:        struct direct *edp;
                    448:        char *buf;
1.13      cgd       449:        size_t buf_size;
1.35.2.1  skrll     450:        int namlen;
1.1       brezak    451:        int rc;
                    452:
                    453:        fp->f_seekp = 0;
1.35.2.1  skrll     454:        while (fp->f_seekp < (off_t)fp->f_di.di_size) {
1.1       brezak    455:                rc = buf_read_file(f, &buf, &buf_size);
                    456:                if (rc)
                    457:                        return (rc);
                    458:
                    459:                dp = (struct direct *)buf;
                    460:                edp = (struct direct *)(buf + buf_size);
1.35.2.1  skrll     461:                for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
                    462:                        if (dp->d_reclen <= 0)
                    463:                                break;
1.1       brezak    464:                        if (dp->d_ino == (ino_t)0)
1.35.2.1  skrll     465:                                continue;
1.1       brezak    466: #if BYTE_ORDER == LITTLE_ENDIAN
                    467:                        if (fp->f_fs->fs_maxsymlinklen <= 0)
                    468:                                namlen = dp->d_type;
                    469:                        else
                    470: #endif
                    471:                                namlen = dp->d_namlen;
                    472:                        if (namlen == length &&
1.35.2.1  skrll     473:                            !memcmp(name, dp->d_name, length)) {
1.1       brezak    474:                                /* found entry */
                    475:                                *inumber_p = dp->d_ino;
                    476:                                return (0);
                    477:                        }
                    478:                }
                    479:                fp->f_seekp += buf_size;
                    480:        }
                    481:        return (ENOENT);
                    482: }
                    483:
1.35      dsl       484: #ifdef LIBSA_FFSv2
1.33      fvdl      485:
                    486: daddr_t sblock_try[] = SBLOCKSEARCH;
                    487:
                    488: static int
1.35.2.1  skrll     489: ffs_find_superblock(struct open_file *f, struct fs *fs)
1.33      fvdl      490: {
                    491:        int i, rc;
                    492:        size_t buf_size;
                    493:
                    494:        for (i = 0; sblock_try[i] != -1; i++) {
                    495:                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.35.2.1  skrll     496:                    sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
1.33      fvdl      497:                if (rc != 0 || buf_size != SBLOCKSIZE)
                    498:                        return rc;
1.35.2.1  skrll     499:                if (fs->fs_sblockloc != sblock_try[i])
                    500:                        /* an alternate superblock - try again */
                    501:                        continue;
1.33      fvdl      502:                if (fs->fs_magic == FS_UFS2_MAGIC) {
                    503:                        return 0;
                    504:                }
                    505:        }
                    506:        return EINVAL;
                    507: }
                    508:
                    509: #endif
                    510:
1.1       brezak    511: /*
                    512:  * Open a file.
                    513:  */
                    514: int
1.35.2.1  skrll     515: ufs_open(const char *path, struct open_file *f)
1.1       brezak    516: {
1.23      cgd       517: #ifndef LIBSA_FS_SINGLECOMPONENT
1.35.2.1  skrll     518:        const char *cp, *ncp;
1.30      augustss  519:        int c;
1.23      cgd       520: #endif
                    521:        ino_t inumber;
1.1       brezak    522:        struct file *fp;
                    523:        struct fs *fs;
1.10      ws        524:        int rc;
1.23      cgd       525: #ifndef LIBSA_NO_FS_SYMLINK
                    526:        ino_t parent_inumber;
1.10      ws        527:        int nlinks = 0;
1.1       brezak    528:        char namebuf[MAXPATHLEN+1];
1.35.2.1  skrll     529:        char *buf;
1.22      simonb    530: #endif
1.1       brezak    531:
                    532:        /* allocate file system specific data structure */
                    533:        fp = alloc(sizeof(struct file));
1.35.2.1  skrll     534:        memset(fp, 0, sizeof(struct file));
1.1       brezak    535:        f->f_fsdata = (void *)fp;
                    536:
                    537:        /* allocate space and read super block */
1.33      fvdl      538:        fs = alloc(SBLOCKSIZE);
1.1       brezak    539:        fp->f_fs = fs;
1.11      mycroft   540:        twiddle();
1.33      fvdl      541:
1.35      dsl       542: #ifdef LIBSA_FFSv2
1.33      fvdl      543:        rc = ffs_find_superblock(f, fs);
                    544:        if (rc)
                    545:                goto out;
                    546: #else
1.35      dsl       547:        {
                    548:                size_t buf_size;
                    549:                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.35.2.1  skrll     550:                        SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
1.35      dsl       551:                if (rc)
                    552:                        goto out;
                    553:                if (buf_size != SBLOCKSIZE ||
                    554: #ifdef LIBSA_FFS
                    555:                    fs->lfs_version != REQUIRED_LFS_VERSION ||
                    556: #endif
                    557:                    fs->fs_magic != FS_MAGIC) {
                    558:                        rc = EINVAL;
                    559:                        goto out;
                    560:                }
1.33      fvdl      561:        }
1.35      dsl       562: #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2
                    563:        /*
                    564:         * XXX  We should check the second superblock and use the eldest
                    565:         *      of the two.  See comments near the top of lfs_mountfs()
                    566:         *      in sys/ufs/lfs/lfs_vfsops.c.
                    567:         *      This may need a LIBSA_LFS_SMALL check as well.
                    568:         */
                    569: #endif
1.33      fvdl      570: #endif
1.1       brezak    571:
1.35      dsl       572: #ifdef LIBSA_FFSv1
1.33      fvdl      573:        ffs_oldfscompat(fs);
1.35      dsl       574: #endif
1.33      fvdl      575:
1.35.2.1  skrll     576:        if (fs->fs_bsize > MAXBSIZE ||
                    577:            (size_t)fs->fs_bsize < sizeof(struct fs)) {
1.1       brezak    578:                rc = EINVAL;
                    579:                goto out;
                    580:        }
                    581:
                    582:        /*
                    583:         * Calculate indirect block levels.
                    584:         */
                    585:        {
1.35.2.1  skrll     586:                indp_t mult;
1.35      dsl       587:                int ln2;
                    588:
                    589:                /*
                    590:                 * We note that the number of indirect blocks is always
                    591:                 * a power of 2.  This lets us use shifts and masks instead
                    592:                 * of divide and remainder and avoinds pulling in the
                    593:                 * 64bit division routine into the boot code.
                    594:                 */
                    595:                mult = NINDIR(fs);
                    596: #ifdef DEBUG
                    597:                if (mult & (mult - 1)) {
                    598:                        /* Hummm was't a power of 2 */
                    599:                        rc = EINVAL;
                    600:                        goto out;
                    601:                }
                    602: #endif
                    603:                for (ln2 = 0; mult != 1; ln2++)
                    604:                        mult >>= 1;
1.1       brezak    605:
1.35.2.1  skrll     606:                fp->f_nishift = ln2;
1.1       brezak    607:        }
                    608:
1.35.2.1  skrll     609:        /* alloc a block sized buffer used for all fs transfers */
                    610:        fp->f_buf = alloc(fs->fs_bsize);
1.1       brezak    611:        inumber = ROOTINO;
                    612:        if ((rc = read_inode(inumber, f)) != 0)
                    613:                goto out;
                    614:
1.23      cgd       615: #ifndef LIBSA_FS_SINGLECOMPONENT
1.1       brezak    616:        cp = path;
                    617:        while (*cp) {
                    618:
                    619:                /*
                    620:                 * Remove extra separators
                    621:                 */
                    622:                while (*cp == '/')
                    623:                        cp++;
                    624:                if (*cp == '\0')
                    625:                        break;
                    626:
                    627:                /*
                    628:                 * Check that current node is a directory.
                    629:                 */
1.35      dsl       630:                if ((fp->f_di.di_mode & IFMT) != IFDIR) {
1.1       brezak    631:                        rc = ENOTDIR;
                    632:                        goto out;
                    633:                }
                    634:
                    635:                /*
                    636:                 * Get next component of path name.
                    637:                 */
1.35.2.1  skrll     638:                ncp = cp;
                    639:                while ((c = *cp) != '\0' && c != '/')
                    640:                        cp++;
1.1       brezak    641:
                    642:                /*
                    643:                 * Look up component in current directory.
                    644:                 * Save directory inumber in case we find a
                    645:                 * symbolic link.
                    646:                 */
1.23      cgd       647: #ifndef LIBSA_NO_FS_SYMLINK
1.1       brezak    648:                parent_inumber = inumber;
1.23      cgd       649: #endif
1.35.2.1  skrll     650:                rc = search_directory(ncp, cp - ncp, f, &inumber);
1.1       brezak    651:                if (rc)
                    652:                        goto out;
                    653:
                    654:                /*
                    655:                 * Open next component.
                    656:                 */
                    657:                if ((rc = read_inode(inumber, f)) != 0)
                    658:                        goto out;
                    659:
1.23      cgd       660: #ifndef LIBSA_NO_FS_SYMLINK
1.1       brezak    661:                /*
                    662:                 * Check for symbolic link.
                    663:                 */
1.35      dsl       664:                if ((fp->f_di.di_mode & IFMT) == IFLNK) {
                    665:                        int link_len = fp->f_di.di_size;
1.10      ws        666:                        int len;
                    667:
                    668:                        len = strlen(cp);
1.1       brezak    669:
1.10      ws        670:                        if (link_len + len > MAXPATHLEN ||
                    671:                            ++nlinks > MAXSYMLINKS) {
1.1       brezak    672:                                rc = ENOENT;
                    673:                                goto out;
                    674:                        }
                    675:
1.35.2.1  skrll     676:                        memmove(&namebuf[link_len], cp, len + 1);
1.1       brezak    677:
1.9       pk        678:                        if (link_len < fs->fs_maxsymlinklen) {
1.35.2.1  skrll     679:                                memcpy(namebuf, fp->f_di.di_db, link_len);
1.1       brezak    680:                        } else {
                    681:                                /*
                    682:                                 * Read file for symbolic link
                    683:                                 */
1.13      cgd       684:                                size_t buf_size;
1.35.2.1  skrll     685:                                indp_t  disk_block;
1.9       pk        686:
1.35.2.1  skrll     687:                                buf = fp->f_buf;
                    688:                                rc = block_map(f, (indp_t)0, &disk_block);
1.9       pk        689:                                if (rc)
                    690:                                        goto out;
1.22      simonb    691:
1.11      mycroft   692:                                twiddle();
1.23      cgd       693:                                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
1.35      dsl       694:                                        F_READ, FSBTODB(fs, disk_block),
1.9       pk        695:                                        fs->fs_bsize, buf, &buf_size);
1.1       brezak    696:                                if (rc)
                    697:                                        goto out;
                    698:
1.35.2.1  skrll     699:                                memcpy(namebuf, buf, link_len);
1.1       brezak    700:                        }
                    701:
                    702:                        /*
                    703:                         * If relative pathname, restart at parent directory.
                    704:                         * If absolute pathname, restart at root.
                    705:                         */
                    706:                        cp = namebuf;
                    707:                        if (*cp != '/')
                    708:                                inumber = parent_inumber;
                    709:                        else
                    710:                                inumber = (ino_t)ROOTINO;
                    711:
1.9       pk        712:                        if ((rc = read_inode(inumber, f)) != 0)
1.1       brezak    713:                                goto out;
                    714:                }
1.23      cgd       715: #endif /* !LIBSA_NO_FS_SYMLINK */
1.1       brezak    716:        }
                    717:
                    718:        /*
                    719:         * Found terminal component.
                    720:         */
                    721:        rc = 0;
1.23      cgd       722:
                    723: #else /* !LIBSA_FS_SINGLECOMPONENT */
                    724:
                    725:        /* look up component in the current (root) directory */
1.35.2.1  skrll     726:        rc = search_directory(path, strlen(path), f, &inumber);
1.23      cgd       727:        if (rc)
                    728:                goto out;
                    729:
                    730:        /* open it */
                    731:        rc = read_inode(inumber, f);
                    732:
                    733: #endif /* !LIBSA_FS_SINGLECOMPONENT */
1.26      cgd       734:
                    735:         fp->f_seekp = 0;               /* reset seek pointer */
1.23      cgd       736:
1.1       brezak    737: out:
1.35.2.1  skrll     738:        if (rc)
                    739:                ufs_close(f);
1.1       brezak    740:        return (rc);
                    741: }
                    742:
                    743: int
1.35.2.1  skrll     744: ufs_close(struct open_file *f)
1.1       brezak    745: {
1.30      augustss  746:        struct file *fp = (struct file *)f->f_fsdata;
1.1       brezak    747:
1.35.2.1  skrll     748:        f->f_fsdata = NULL;
                    749:        if (fp == NULL)
1.1       brezak    750:                return (0);
                    751:
                    752:        if (fp->f_buf)
                    753:                free(fp->f_buf, fp->f_fs->fs_bsize);
1.33      fvdl      754:        free(fp->f_fs, SBLOCKSIZE);
1.1       brezak    755:        free(fp, sizeof(struct file));
                    756:        return (0);
                    757: }
                    758:
                    759: /*
                    760:  * Copy a portion of a file into kernel memory.
                    761:  * Cross block boundaries when necessary.
                    762:  */
                    763: int
1.35.2.1  skrll     764: ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
1.1       brezak    765: {
1.30      augustss  766:        struct file *fp = (struct file *)f->f_fsdata;
                    767:        size_t csize;
1.1       brezak    768:        char *buf;
1.13      cgd       769:        size_t buf_size;
1.1       brezak    770:        int rc = 0;
1.30      augustss  771:        char *addr = start;
1.1       brezak    772:
                    773:        while (size != 0) {
1.35.2.1  skrll     774:                if (fp->f_seekp >= (off_t)fp->f_di.di_size)
1.1       brezak    775:                        break;
                    776:
                    777:                rc = buf_read_file(f, &buf, &buf_size);
                    778:                if (rc)
                    779:                        break;
                    780:
                    781:                csize = size;
                    782:                if (csize > buf_size)
                    783:                        csize = buf_size;
                    784:
1.35.2.1  skrll     785:                memcpy(addr, buf, csize);
1.1       brezak    786:
                    787:                fp->f_seekp += csize;
1.12      pk        788:                addr += csize;
1.1       brezak    789:                size -= csize;
                    790:        }
                    791:        if (resid)
                    792:                *resid = size;
                    793:        return (rc);
                    794: }
                    795:
                    796: /*
                    797:  * Not implemented.
                    798:  */
1.23      cgd       799: #ifndef LIBSA_NO_FS_WRITE
1.1       brezak    800: int
1.35.2.1  skrll     801: ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
1.1       brezak    802: {
                    803:
                    804:        return (EROFS);
                    805: }
1.23      cgd       806: #endif /* !LIBSA_NO_FS_WRITE */
1.1       brezak    807:
1.23      cgd       808: #ifndef LIBSA_NO_FS_SEEK
1.1       brezak    809: off_t
1.35.2.1  skrll     810: ufs_seek(struct open_file *f, off_t offset, int where)
1.1       brezak    811: {
1.30      augustss  812:        struct file *fp = (struct file *)f->f_fsdata;
1.1       brezak    813:
                    814:        switch (where) {
                    815:        case SEEK_SET:
                    816:                fp->f_seekp = offset;
                    817:                break;
                    818:        case SEEK_CUR:
                    819:                fp->f_seekp += offset;
                    820:                break;
                    821:        case SEEK_END:
1.35      dsl       822:                fp->f_seekp = fp->f_di.di_size - offset;
1.1       brezak    823:                break;
                    824:        default:
                    825:                return (-1);
                    826:        }
                    827:        return (fp->f_seekp);
                    828: }
1.23      cgd       829: #endif /* !LIBSA_NO_FS_SEEK */
1.1       brezak    830:
                    831: int
1.35.2.1  skrll     832: ufs_stat(struct open_file *f, struct stat *sb)
1.1       brezak    833: {
1.30      augustss  834:        struct file *fp = (struct file *)f->f_fsdata;
1.1       brezak    835:
                    836:        /* only important stuff */
1.35.2.1  skrll     837:        memset(sb, 0, sizeof *sb);
1.35      dsl       838:        sb->st_mode = fp->f_di.di_mode;
                    839:        sb->st_uid = fp->f_di.di_uid;
                    840:        sb->st_gid = fp->f_di.di_gid;
                    841:        sb->st_size = fp->f_di.di_size;
1.4       pk        842:        return (0);
                    843: }
                    844:
1.35      dsl       845: #ifdef LIBSA_FFSv1
1.4       pk        846: /*
                    847:  * Sanity checks for old file systems.
                    848:  *
                    849:  * XXX - goes away some day.
1.35.2.1  skrll     850:  * Stripped of stuff libsa doesn't need.....
1.4       pk        851:  */
1.13      cgd       852: static void
1.35.2.1  skrll     853: ffs_oldfscompat(struct fs *fs)
1.4       pk        854: {
                    855:
1.33      fvdl      856: #ifdef COMPAT_UFS
                    857:        if (fs->fs_magic == FS_UFS1_MAGIC &&
                    858:            fs->fs_old_inodefmt < FS_44INODEFMT) {
                    859:                fs->fs_qbmask = ~fs->fs_bmask;
                    860:                fs->fs_qfmask = ~fs->fs_fmask;
                    861:        }
                    862: #endif
1.1       brezak    863: }
1.35      dsl       864: #endif

CVSweb <webmaster@jp.NetBSD.org>