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>