[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.48.4.1

1.48.4.1! kardel      1: /*     $NetBSD: ufs.c,v 1.48 2006/01/25 18:27:23 christos 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.36      agc        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.37      dsl        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.40      dsl       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
1.47      uwe       135: #define indp_t         int32_t
1.35      dsl       136: #endif
1.45      christos  137: typedef uint32_t       ino32_t;
1.35      dsl       138: #ifndef FSBTODB
1.40      dsl       139: #define FSBTODB(fs, indp) fsbtodb(fs, indp)
1.33      fvdl      140: #endif
1.23      cgd       141:
1.1       brezak    142: /*
1.40      dsl       143:  * To avoid having a lot of filesystem-block sized buffers lurking (which
                    144:  * could be 32k) we only keep a few entries of the indirect block map.
                    145:  * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
                    146:  * ~13 times pulling in a 6M kernel.
                    147:  * The cache size must be smaller than the smallest filesystem block,
                    148:  * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
                    149:  */
                    150: #define LN2_IND_CACHE_SZ       6
                    151: #define IND_CACHE_SZ           (1 << LN2_IND_CACHE_SZ)
                    152: #define IND_CACHE_MASK         (IND_CACHE_SZ - 1)
                    153:
                    154: /*
1.1       brezak    155:  * In-core open file.
                    156:  */
                    157: struct file {
                    158:        off_t           f_seekp;        /* seek pointer */
                    159:        struct fs       *f_fs;          /* pointer to super-block */
1.35      dsl       160:        struct ufs_dinode       f_di;           /* copy of on-disk inode */
1.40      dsl       161:        uint            f_nishift;      /* for blocks in indirect block */
                    162:        indp_t          f_ind_cache_block;
                    163:        indp_t          f_ind_cache[IND_CACHE_SZ];
                    164:
1.1       brezak    165:        char            *f_buf;         /* buffer for data block */
1.13      cgd       166:        size_t          f_buf_size;     /* size of data block */
1.1       brezak    167:        daddr_t         f_buf_blkno;    /* block number of data block */
                    168: };
                    169:
1.45      christos  170: static int read_inode(ino32_t, struct open_file *);
1.40      dsl       171: static int block_map(struct open_file *, indp_t, indp_t *);
1.38      dsl       172: static int buf_read_file(struct open_file *, char **, size_t *);
1.45      christos  173: static int search_directory(const char *, int, struct open_file *, ino32_t *);
1.35      dsl       174: #ifdef LIBSA_FFSv1
1.38      dsl       175: static void ffs_oldfscompat(struct fs *);
1.35      dsl       176: #endif
                    177: #ifdef LIBSA_FFSv2
1.38      dsl       178: static int ffs_find_superblock(struct open_file *, struct fs *);
1.35      dsl       179: #endif
                    180:
                    181: #ifdef LIBSA_LFS
                    182: /*
                    183:  * Find an inode's block.  Look it up in the ifile.  Whee!
                    184:  */
                    185: static int
1.45      christos  186: find_inode_sector(ino32_t inumber, struct open_file *f, daddr_t *isp)
1.35      dsl       187: {
                    188:        struct file *fp = (struct file *)f->f_fsdata;
                    189:        struct fs *fs = fp->f_fs;
                    190:        daddr_t ifileent_blkno;
                    191:        char *ent_in_buf;
                    192:        size_t buf_after_ent;
                    193:        int rc;
1.33      fvdl      194:
1.35      dsl       195:        rc = read_inode(fs->lfs_ifile, f);
                    196:        if (rc)
                    197:                return (rc);
                    198:
                    199:        ifileent_blkno =
                    200:            (inumber / fs->lfs_ifpb) + fs->lfs_cleansz + fs->lfs_segtabsz;
                    201:        fp->f_seekp = (off_t)ifileent_blkno * fs->fs_bsize +
                    202:            (inumber % fs->lfs_ifpb) * sizeof (IFILE_Vx);
                    203:        rc = buf_read_file(f, &ent_in_buf, &buf_after_ent);
                    204:        if (rc)
                    205:                return (rc);
                    206:        /* make sure something's not badly wrong, but don't panic. */
                    207:        if (buf_after_ent < sizeof (IFILE_Vx))
                    208:                return (EINVAL);
                    209:
                    210:        *isp = FSBTODB(fs, ((IFILE_Vx *)ent_in_buf)->if_daddr);
                    211:        if (*isp == LFS_UNUSED_DADDR)   /* again, something badly wrong */
                    212:                return (EINVAL);
                    213:        return (0);
                    214: }
1.7       brezak    215: #endif
                    216:
1.1       brezak    217: /*
                    218:  * Read a new inode into a file structure.
                    219:  */
                    220: static int
1.45      christos  221: read_inode(ino32_t inumber, struct open_file *f)
1.1       brezak    222: {
1.30      augustss  223:        struct file *fp = (struct file *)f->f_fsdata;
                    224:        struct fs *fs = fp->f_fs;
1.1       brezak    225:        char *buf;
1.48.4.1! kardel    226:        size_t rsize;
1.1       brezak    227:        int rc;
1.35      dsl       228:        daddr_t inode_sector;
                    229: #ifdef LIBSA_LFS
                    230:        struct ufs_dinode *dip;
                    231:        int cnt;
                    232: #endif
                    233:
                    234: #ifdef LIBSA_LFS
                    235:        if (inumber == fs->lfs_ifile)
                    236:                inode_sector = FSBTODB(fs, fs->lfs_idaddr);
                    237:        else if ((rc = find_inode_sector(inumber, f, &inode_sector)) != 0)
                    238:                return (rc);
                    239: #else
                    240:        inode_sector = FSBTODB(fs, ino_to_fsba(fs, inumber));
                    241: #endif
1.1       brezak    242:
                    243:        /*
                    244:         * Read inode and save it.
                    245:         */
1.40      dsl       246:        buf = fp->f_buf;
1.11      mycroft   247:        twiddle();
1.23      cgd       248:        rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.40      dsl       249:            inode_sector, fs->fs_bsize, buf, &rsize);
1.1       brezak    250:        if (rc)
1.40      dsl       251:                return rc;
1.48.4.1! kardel    252:        if (rsize != fs->fs_bsize)
1.40      dsl       253:                return EIO;
1.1       brezak    254:
1.35      dsl       255: #ifdef LIBSA_LFS
                    256:        cnt = INOPBx(fs);
1.40      dsl       257:        dip = (struct ufs_dinode *)buf + (cnt - 1);
                    258:        for (; dip->di_inumber != inumber; --dip) {
                    259:                /* kernel code panics, but boot blocks which panic are Bad. */
                    260:                if (--cnt == 0)
                    261:                        return EINVAL;
1.1       brezak    262:        }
1.35      dsl       263:        fp->f_di = *dip;
                    264: #else
                    265:        fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)];
                    266: #endif
1.1       brezak    267:
                    268:        /*
                    269:         * Clear out the old buffers
                    270:         */
1.40      dsl       271:        fp->f_ind_cache_block = ~0;
                    272:        fp->f_buf_blkno = -1;
1.22      simonb    273:        return (rc);
1.1       brezak    274: }
                    275:
                    276: /*
                    277:  * Given an offset in a file, find the disk block number that
                    278:  * contains that block.
                    279:  */
                    280: static int
1.40      dsl       281: block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
1.1       brezak    282: {
1.30      augustss  283:        struct file *fp = (struct file *)f->f_fsdata;
                    284:        struct fs *fs = fp->f_fs;
1.42      fvdl      285:        unsigned level;
1.40      dsl       286:        indp_t ind_cache;
                    287:        indp_t ind_block_num;
1.48.4.1! kardel    288:        size_t rsize;
1.1       brezak    289:        int rc;
1.40      dsl       290:        indp_t *buf = (void *)fp->f_buf;
1.1       brezak    291:
                    292:        /*
                    293:         * Index structure of an inode:
                    294:         *
                    295:         * di_db[0..NDADDR-1]   hold block numbers for blocks
                    296:         *                      0..NDADDR-1
                    297:         *
                    298:         * di_ib[0]             index block 0 is the single indirect block
                    299:         *                      holds block numbers for blocks
                    300:         *                      NDADDR .. NDADDR + NINDIR(fs)-1
                    301:         *
                    302:         * di_ib[1]             index block 1 is the double indirect block
                    303:         *                      holds block numbers for INDEX blocks for blocks
                    304:         *                      NDADDR + NINDIR(fs) ..
                    305:         *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
                    306:         *
                    307:         * di_ib[2]             index block 2 is the triple indirect block
                    308:         *                      holds block numbers for double-indirect
                    309:         *                      blocks for blocks
                    310:         *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
                    311:         *                      NDADDR + NINDIR(fs) + NINDIR(fs)**2
                    312:         *                              + NINDIR(fs)**3 - 1
                    313:         */
                    314:
                    315:        if (file_block < NDADDR) {
                    316:                /* Direct block. */
1.35      dsl       317:                *disk_block_p = fp->f_di.di_db[file_block];
1.1       brezak    318:                return (0);
                    319:        }
                    320:
                    321:        file_block -= NDADDR;
                    322:
1.40      dsl       323:        ind_cache = file_block >> LN2_IND_CACHE_SZ;
                    324:        if (ind_cache == fp->f_ind_cache_block) {
                    325:                *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK];
                    326:                return 0;
                    327:        }
                    328:
                    329:        for (level = 0;;) {
                    330:                level += fp->f_nishift;
                    331:                if (file_block < (indp_t)1 << level)
                    332:                        break;
                    333:                if (level > NIADDR * fp->f_nishift)
1.38      dsl       334:                        /* Block number too high */
                    335:                        return (EFBIG);
1.40      dsl       336:                file_block -= (indp_t)1 << level;
1.1       brezak    337:        }
                    338:
1.40      dsl       339:        ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1];
1.1       brezak    340:
1.40      dsl       341:        for (;;) {
                    342:                level -= fp->f_nishift;
1.1       brezak    343:                if (ind_block_num == 0) {
                    344:                        *disk_block_p = 0;      /* missing */
                    345:                        return (0);
                    346:                }
                    347:
1.40      dsl       348:                twiddle();
                    349:                /*
                    350:                 * If we were feeling brave, we could work out the number
                    351:                 * of the disk sector and read a single disk sector instead
                    352:                 * of a filesystem block.
                    353:                 * However we don't do this very often anyway...
                    354:                 */
                    355:                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
                    356:                        FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize,
                    357:                        buf, &rsize);
                    358:                if (rc)
                    359:                        return (rc);
1.48.4.1! kardel    360:                if (rsize != fs->fs_bsize)
1.40      dsl       361:                        return EIO;
                    362:                ind_block_num = buf[file_block >> level];
                    363:                if (level == 0)
                    364:                        break;
                    365:                file_block &= (1 << level) - 1;
                    366:        }
1.1       brezak    367:
1.40      dsl       368:        /* Save the part of the block that contains this sector */
                    369:        memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
                    370:            IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
                    371:        fp->f_ind_cache_block = ind_cache;
1.1       brezak    372:
                    373:        *disk_block_p = ind_block_num;
                    374:
                    375:        return (0);
                    376: }
                    377:
                    378: /*
1.40      dsl       379:  * Read a portion of a file into an internal buffer.
                    380:  * Return the location in the buffer and the amount in the buffer.
1.1       brezak    381:  */
                    382: static int
1.37      dsl       383: buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
1.1       brezak    384: {
1.30      augustss  385:        struct file *fp = (struct file *)f->f_fsdata;
                    386:        struct fs *fs = fp->f_fs;
1.1       brezak    387:        long off;
1.40      dsl       388:        indp_t file_block;
                    389:        indp_t disk_block;
1.13      cgd       390:        size_t block_size;
1.1       brezak    391:        int rc;
                    392:
                    393:        off = blkoff(fs, fp->f_seekp);
                    394:        file_block = lblkno(fs, fp->f_seekp);
1.35      dsl       395: #ifdef LIBSA_LFS
                    396:        block_size = dblksize(fs, &fp->f_di, file_block);
                    397: #else
1.42      fvdl      398:        block_size = sblksize(fs, (int64_t)fp->f_di.di_size, file_block);
1.35      dsl       399: #endif
1.1       brezak    400:
                    401:        if (file_block != fp->f_buf_blkno) {
                    402:                rc = block_map(f, file_block, &disk_block);
                    403:                if (rc)
                    404:                        return (rc);
                    405:
                    406:                if (disk_block == 0) {
1.41      dsl       407:                        memset(fp->f_buf, 0, block_size);
1.1       brezak    408:                        fp->f_buf_size = block_size;
                    409:                } else {
1.11      mycroft   410:                        twiddle();
1.23      cgd       411:                        rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.35      dsl       412:                                FSBTODB(fs, disk_block),
1.1       brezak    413:                                block_size, fp->f_buf, &fp->f_buf_size);
                    414:                        if (rc)
                    415:                                return (rc);
                    416:                }
                    417:
                    418:                fp->f_buf_blkno = file_block;
                    419:        }
                    420:
                    421:        /*
                    422:         * Return address of byte in buffer corresponding to
                    423:         * offset, and size of remainder of buffer after that
                    424:         * byte.
                    425:         */
                    426:        *buf_p = fp->f_buf + off;
                    427:        *size_p = block_size - off;
                    428:
                    429:        /*
                    430:         * But truncate buffer at end of file.
                    431:         */
1.35      dsl       432:        if (*size_p > fp->f_di.di_size - fp->f_seekp)
                    433:                *size_p = fp->f_di.di_size - fp->f_seekp;
1.1       brezak    434:
                    435:        return (0);
                    436: }
                    437:
                    438: /*
                    439:  * Search a directory for a name and return its
1.38      dsl       440:  * inode number.
1.1       brezak    441:  */
                    442: static int
1.38      dsl       443: search_directory(const char *name, int length, struct open_file *f,
1.45      christos  444:     ino32_t *inumber_p)
1.1       brezak    445: {
1.30      augustss  446:        struct file *fp = (struct file *)f->f_fsdata;
                    447:        struct direct *dp;
1.1       brezak    448:        struct direct *edp;
                    449:        char *buf;
1.13      cgd       450:        size_t buf_size;
1.38      dsl       451:        int namlen;
1.1       brezak    452:        int rc;
                    453:
                    454:        fp->f_seekp = 0;
1.42      fvdl      455:        while (fp->f_seekp < (off_t)fp->f_di.di_size) {
1.1       brezak    456:                rc = buf_read_file(f, &buf, &buf_size);
                    457:                if (rc)
                    458:                        return (rc);
                    459:
                    460:                dp = (struct direct *)buf;
                    461:                edp = (struct direct *)(buf + buf_size);
1.38      dsl       462:                for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
1.40      dsl       463:                        if (dp->d_reclen <= 0)
                    464:                                break;
1.45      christos  465:                        if (dp->d_ino == (ino32_t)0)
1.38      dsl       466:                                continue;
1.1       brezak    467: #if BYTE_ORDER == LITTLE_ENDIAN
                    468:                        if (fp->f_fs->fs_maxsymlinklen <= 0)
                    469:                                namlen = dp->d_type;
                    470:                        else
                    471: #endif
                    472:                                namlen = dp->d_namlen;
                    473:                        if (namlen == length &&
1.38      dsl       474:                            !memcmp(name, dp->d_name, length)) {
1.1       brezak    475:                                /* found entry */
                    476:                                *inumber_p = dp->d_ino;
                    477:                                return (0);
                    478:                        }
                    479:                }
                    480:                fp->f_seekp += buf_size;
                    481:        }
                    482:        return (ENOENT);
                    483: }
                    484:
1.35      dsl       485: #ifdef LIBSA_FFSv2
1.33      fvdl      486:
                    487: daddr_t sblock_try[] = SBLOCKSEARCH;
                    488:
                    489: static int
1.37      dsl       490: ffs_find_superblock(struct open_file *f, struct fs *fs)
1.33      fvdl      491: {
                    492:        int i, rc;
                    493:        size_t buf_size;
                    494:
                    495:        for (i = 0; sblock_try[i] != -1; i++) {
                    496:                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.40      dsl       497:                    sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
1.33      fvdl      498:                if (rc != 0 || buf_size != SBLOCKSIZE)
                    499:                        return rc;
1.43      dsl       500:                if (fs->fs_sblockloc != sblock_try[i])
                    501:                        /* an alternate superblock - try again */
                    502:                        continue;
1.33      fvdl      503:                if (fs->fs_magic == FS_UFS2_MAGIC) {
                    504:                        return 0;
                    505:                }
                    506:        }
                    507:        return EINVAL;
                    508: }
                    509:
                    510: #endif
                    511:
1.1       brezak    512: /*
                    513:  * Open a file.
                    514:  */
                    515: int
1.38      dsl       516: ufs_open(const char *path, struct open_file *f)
1.1       brezak    517: {
1.23      cgd       518: #ifndef LIBSA_FS_SINGLECOMPONENT
1.38      dsl       519:        const char *cp, *ncp;
1.30      augustss  520:        int c;
1.23      cgd       521: #endif
1.45      christos  522:        ino32_t inumber;
1.1       brezak    523:        struct file *fp;
                    524:        struct fs *fs;
1.10      ws        525:        int rc;
1.23      cgd       526: #ifndef LIBSA_NO_FS_SYMLINK
1.45      christos  527:        ino32_t parent_inumber;
1.10      ws        528:        int nlinks = 0;
1.1       brezak    529:        char namebuf[MAXPATHLEN+1];
1.40      dsl       530:        char *buf;
1.22      simonb    531: #endif
1.1       brezak    532:
                    533:        /* allocate file system specific data structure */
                    534:        fp = alloc(sizeof(struct file));
1.41      dsl       535:        memset(fp, 0, sizeof(struct file));
1.1       brezak    536:        f->f_fsdata = (void *)fp;
                    537:
                    538:        /* allocate space and read super block */
1.33      fvdl      539:        fs = alloc(SBLOCKSIZE);
1.1       brezak    540:        fp->f_fs = fs;
1.11      mycroft   541:        twiddle();
1.33      fvdl      542:
1.35      dsl       543: #ifdef LIBSA_FFSv2
1.33      fvdl      544:        rc = ffs_find_superblock(f, fs);
                    545:        if (rc)
                    546:                goto out;
                    547: #else
1.35      dsl       548:        {
                    549:                size_t buf_size;
                    550:                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
1.40      dsl       551:                        SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
1.35      dsl       552:                if (rc)
                    553:                        goto out;
                    554:                if (buf_size != SBLOCKSIZE ||
                    555: #ifdef LIBSA_FFS
                    556:                    fs->lfs_version != REQUIRED_LFS_VERSION ||
                    557: #endif
                    558:                    fs->fs_magic != FS_MAGIC) {
                    559:                        rc = EINVAL;
                    560:                        goto out;
                    561:                }
1.33      fvdl      562:        }
1.35      dsl       563: #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2
                    564:        /*
                    565:         * XXX  We should check the second superblock and use the eldest
                    566:         *      of the two.  See comments near the top of lfs_mountfs()
                    567:         *      in sys/ufs/lfs/lfs_vfsops.c.
                    568:         *      This may need a LIBSA_LFS_SMALL check as well.
                    569:         */
                    570: #endif
1.33      fvdl      571: #endif
1.1       brezak    572:
1.35      dsl       573: #ifdef LIBSA_FFSv1
1.33      fvdl      574:        ffs_oldfscompat(fs);
1.35      dsl       575: #endif
1.33      fvdl      576:
1.42      fvdl      577:        if (fs->fs_bsize > MAXBSIZE ||
                    578:            (size_t)fs->fs_bsize < sizeof(struct fs)) {
1.1       brezak    579:                rc = EINVAL;
                    580:                goto out;
                    581:        }
                    582:
                    583:        /*
                    584:         * Calculate indirect block levels.
                    585:         */
                    586:        {
1.40      dsl       587:                indp_t mult;
1.35      dsl       588:                int ln2;
                    589:
                    590:                /*
                    591:                 * We note that the number of indirect blocks is always
                    592:                 * a power of 2.  This lets us use shifts and masks instead
                    593:                 * of divide and remainder and avoinds pulling in the
                    594:                 * 64bit division routine into the boot code.
                    595:                 */
                    596:                mult = NINDIR(fs);
                    597: #ifdef DEBUG
                    598:                if (mult & (mult - 1)) {
                    599:                        /* Hummm was't a power of 2 */
                    600:                        rc = EINVAL;
                    601:                        goto out;
                    602:                }
                    603: #endif
                    604:                for (ln2 = 0; mult != 1; ln2++)
                    605:                        mult >>= 1;
1.1       brezak    606:
1.40      dsl       607:                fp->f_nishift = ln2;
1.1       brezak    608:        }
                    609:
1.40      dsl       610:        /* alloc a block sized buffer used for all fs transfers */
                    611:        fp->f_buf = alloc(fs->fs_bsize);
1.1       brezak    612:        inumber = ROOTINO;
                    613:        if ((rc = read_inode(inumber, f)) != 0)
                    614:                goto out;
                    615:
1.23      cgd       616: #ifndef LIBSA_FS_SINGLECOMPONENT
1.1       brezak    617:        cp = path;
                    618:        while (*cp) {
                    619:
                    620:                /*
                    621:                 * Remove extra separators
                    622:                 */
                    623:                while (*cp == '/')
                    624:                        cp++;
                    625:                if (*cp == '\0')
                    626:                        break;
                    627:
                    628:                /*
                    629:                 * Check that current node is a directory.
                    630:                 */
1.35      dsl       631:                if ((fp->f_di.di_mode & IFMT) != IFDIR) {
1.1       brezak    632:                        rc = ENOTDIR;
                    633:                        goto out;
                    634:                }
                    635:
                    636:                /*
                    637:                 * Get next component of path name.
                    638:                 */
1.38      dsl       639:                ncp = cp;
                    640:                while ((c = *cp) != '\0' && c != '/')
                    641:                        cp++;
1.1       brezak    642:
                    643:                /*
                    644:                 * Look up component in current directory.
                    645:                 * Save directory inumber in case we find a
                    646:                 * symbolic link.
                    647:                 */
1.23      cgd       648: #ifndef LIBSA_NO_FS_SYMLINK
1.1       brezak    649:                parent_inumber = inumber;
1.23      cgd       650: #endif
1.38      dsl       651:                rc = search_directory(ncp, cp - ncp, f, &inumber);
1.1       brezak    652:                if (rc)
                    653:                        goto out;
                    654:
                    655:                /*
                    656:                 * Open next component.
                    657:                 */
                    658:                if ((rc = read_inode(inumber, f)) != 0)
                    659:                        goto out;
                    660:
1.23      cgd       661: #ifndef LIBSA_NO_FS_SYMLINK
1.1       brezak    662:                /*
                    663:                 * Check for symbolic link.
                    664:                 */
1.35      dsl       665:                if ((fp->f_di.di_mode & IFMT) == IFLNK) {
                    666:                        int link_len = fp->f_di.di_size;
1.10      ws        667:                        int len;
                    668:
                    669:                        len = strlen(cp);
1.1       brezak    670:
1.10      ws        671:                        if (link_len + len > MAXPATHLEN ||
                    672:                            ++nlinks > MAXSYMLINKS) {
1.1       brezak    673:                                rc = ENOENT;
                    674:                                goto out;
                    675:                        }
                    676:
1.38      dsl       677:                        memmove(&namebuf[link_len], cp, len + 1);
1.1       brezak    678:
1.9       pk        679:                        if (link_len < fs->fs_maxsymlinklen) {
1.38      dsl       680:                                memcpy(namebuf, fp->f_di.di_db, link_len);
1.1       brezak    681:                        } else {
                    682:                                /*
                    683:                                 * Read file for symbolic link
                    684:                                 */
1.13      cgd       685:                                size_t buf_size;
1.40      dsl       686:                                indp_t  disk_block;
1.9       pk        687:
1.40      dsl       688:                                buf = fp->f_buf;
                    689:                                rc = block_map(f, (indp_t)0, &disk_block);
1.9       pk        690:                                if (rc)
                    691:                                        goto out;
1.22      simonb    692:
1.11      mycroft   693:                                twiddle();
1.23      cgd       694:                                rc = DEV_STRATEGY(f->f_dev)(f->f_devdata,
1.35      dsl       695:                                        F_READ, FSBTODB(fs, disk_block),
1.9       pk        696:                                        fs->fs_bsize, buf, &buf_size);
1.1       brezak    697:                                if (rc)
                    698:                                        goto out;
                    699:
1.38      dsl       700:                                memcpy(namebuf, buf, link_len);
1.1       brezak    701:                        }
                    702:
                    703:                        /*
                    704:                         * If relative pathname, restart at parent directory.
                    705:                         * If absolute pathname, restart at root.
                    706:                         */
                    707:                        cp = namebuf;
                    708:                        if (*cp != '/')
                    709:                                inumber = parent_inumber;
                    710:                        else
1.45      christos  711:                                inumber = (ino32_t)ROOTINO;
1.1       brezak    712:
1.9       pk        713:                        if ((rc = read_inode(inumber, f)) != 0)
1.1       brezak    714:                                goto out;
                    715:                }
1.23      cgd       716: #endif /* !LIBSA_NO_FS_SYMLINK */
1.1       brezak    717:        }
                    718:
                    719:        /*
                    720:         * Found terminal component.
                    721:         */
                    722:        rc = 0;
1.23      cgd       723:
                    724: #else /* !LIBSA_FS_SINGLECOMPONENT */
                    725:
                    726:        /* look up component in the current (root) directory */
1.38      dsl       727:        rc = search_directory(path, strlen(path), f, &inumber);
1.23      cgd       728:        if (rc)
                    729:                goto out;
                    730:
                    731:        /* open it */
                    732:        rc = read_inode(inumber, f);
                    733:
                    734: #endif /* !LIBSA_FS_SINGLECOMPONENT */
1.26      cgd       735:
                    736:         fp->f_seekp = 0;               /* reset seek pointer */
1.23      cgd       737:
1.1       brezak    738: out:
1.40      dsl       739:        if (rc)
1.38      dsl       740:                ufs_close(f);
1.1       brezak    741:        return (rc);
                    742: }
                    743:
                    744: int
1.37      dsl       745: ufs_close(struct open_file *f)
1.1       brezak    746: {
1.30      augustss  747:        struct file *fp = (struct file *)f->f_fsdata;
1.1       brezak    748:
1.38      dsl       749:        f->f_fsdata = NULL;
                    750:        if (fp == NULL)
1.1       brezak    751:                return (0);
                    752:
                    753:        if (fp->f_buf)
1.48      christos  754:                dealloc(fp->f_buf, fp->f_fs->fs_bsize);
                    755:        dealloc(fp->f_fs, SBLOCKSIZE);
                    756:        dealloc(fp, sizeof(struct file));
1.1       brezak    757:        return (0);
                    758: }
                    759:
                    760: /*
                    761:  * Copy a portion of a file into kernel memory.
                    762:  * Cross block boundaries when necessary.
                    763:  */
                    764: int
1.37      dsl       765: ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
1.1       brezak    766: {
1.30      augustss  767:        struct file *fp = (struct file *)f->f_fsdata;
                    768:        size_t csize;
1.1       brezak    769:        char *buf;
1.13      cgd       770:        size_t buf_size;
1.1       brezak    771:        int rc = 0;
1.30      augustss  772:        char *addr = start;
1.1       brezak    773:
                    774:        while (size != 0) {
1.42      fvdl      775:                if (fp->f_seekp >= (off_t)fp->f_di.di_size)
1.1       brezak    776:                        break;
                    777:
                    778:                rc = buf_read_file(f, &buf, &buf_size);
                    779:                if (rc)
                    780:                        break;
                    781:
                    782:                csize = size;
                    783:                if (csize > buf_size)
                    784:                        csize = buf_size;
                    785:
1.38      dsl       786:                memcpy(addr, buf, csize);
1.1       brezak    787:
                    788:                fp->f_seekp += csize;
1.12      pk        789:                addr += csize;
1.1       brezak    790:                size -= csize;
                    791:        }
                    792:        if (resid)
                    793:                *resid = size;
                    794:        return (rc);
                    795: }
                    796:
                    797: /*
                    798:  * Not implemented.
                    799:  */
1.23      cgd       800: #ifndef LIBSA_NO_FS_WRITE
1.1       brezak    801: int
1.37      dsl       802: ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
1.1       brezak    803: {
                    804:
                    805:        return (EROFS);
                    806: }
1.23      cgd       807: #endif /* !LIBSA_NO_FS_WRITE */
1.1       brezak    808:
1.23      cgd       809: #ifndef LIBSA_NO_FS_SEEK
1.1       brezak    810: off_t
1.37      dsl       811: ufs_seek(struct open_file *f, off_t offset, int where)
1.1       brezak    812: {
1.30      augustss  813:        struct file *fp = (struct file *)f->f_fsdata;
1.1       brezak    814:
                    815:        switch (where) {
                    816:        case SEEK_SET:
                    817:                fp->f_seekp = offset;
                    818:                break;
                    819:        case SEEK_CUR:
                    820:                fp->f_seekp += offset;
                    821:                break;
                    822:        case SEEK_END:
1.35      dsl       823:                fp->f_seekp = fp->f_di.di_size - offset;
1.1       brezak    824:                break;
                    825:        default:
                    826:                return (-1);
                    827:        }
                    828:        return (fp->f_seekp);
                    829: }
1.23      cgd       830: #endif /* !LIBSA_NO_FS_SEEK */
1.1       brezak    831:
                    832: int
1.37      dsl       833: ufs_stat(struct open_file *f, struct stat *sb)
1.1       brezak    834: {
1.30      augustss  835:        struct file *fp = (struct file *)f->f_fsdata;
1.1       brezak    836:
                    837:        /* only important stuff */
1.40      dsl       838:        memset(sb, 0, sizeof *sb);
1.35      dsl       839:        sb->st_mode = fp->f_di.di_mode;
                    840:        sb->st_uid = fp->f_di.di_uid;
                    841:        sb->st_gid = fp->f_di.di_gid;
                    842:        sb->st_size = fp->f_di.di_size;
1.4       pk        843:        return (0);
                    844: }
                    845:
1.35      dsl       846: #ifdef LIBSA_FFSv1
1.4       pk        847: /*
                    848:  * Sanity checks for old file systems.
                    849:  *
                    850:  * XXX - goes away some day.
1.40      dsl       851:  * Stripped of stuff libsa doesn't need.....
1.4       pk        852:  */
1.13      cgd       853: static void
1.37      dsl       854: ffs_oldfscompat(struct fs *fs)
1.4       pk        855: {
                    856:
1.33      fvdl      857: #ifdef COMPAT_UFS
                    858:        if (fs->fs_magic == FS_UFS1_MAGIC &&
1.44      perry     859:            fs->fs_old_inodefmt < FS_44INODEFMT) {
1.33      fvdl      860:                fs->fs_qbmask = ~fs->fs_bmask;
                    861:                fs->fs_qfmask = ~fs->fs_fmask;
                    862:        }
                    863: #endif
1.1       brezak    864: }
1.35      dsl       865: #endif

CVSweb <webmaster@jp.NetBSD.org>