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>