summaryrefslogtreecommitdiffstats
path: root/lib/libstand/ufs.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libstand/ufs.c')
-rw-r--r--lib/libstand/ufs.c185
1 files changed, 90 insertions, 95 deletions
diff --git a/lib/libstand/ufs.c b/lib/libstand/ufs.c
index 2bd9d17..8993d6c 100644
--- a/lib/libstand/ufs.c
+++ b/lib/libstand/ufs.c
@@ -1,7 +1,16 @@
/* $NetBSD: ufs.c,v 1.20 1998/03/01 07:15:39 ross Exp $ */
/*-
- * Copyright (c) 1993
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Marshall
+ * Kirk McKusick and Network Associates Laboratories, the Security
+ * Research Division of Network Associates, Inc. under DARPA/SPAWAR
+ * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+ * research program
+ *
+ * Copyright (c) 1982, 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
@@ -107,7 +116,10 @@ struct fs_ops ufs_fsops = {
struct file {
off_t f_seekp; /* seek pointer */
struct fs *f_fs; /* pointer to super-block */
- struct dinode f_di; /* copy of on-disk inode */
+ union dinode {
+ struct ufs1_dinode di1;
+ struct ufs2_dinode di2;
+ } f_di; /* copy of on-disk inode */
int f_nindir[NIADDR];
/* number of blocks mapped by
indirect block at level i */
@@ -115,20 +127,20 @@ struct file {
level i */
size_t f_blksize[NIADDR];
/* size of buffer */
- daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
+ ufs2_daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
+ ufs2_daddr_t f_buf_blkno; /* block number of data block */
char *f_buf; /* buffer for data block */
size_t f_buf_size; /* size of data block */
- daddr_t f_buf_blkno; /* block number of data block */
};
+#define DIP(fp, field) \
+ ((fp)->f_fs->fs_magic == FS_UFS1_MAGIC ? \
+ (fp)->f_di.di1.field : (fp)->f_di.di2.field)
static int read_inode(ino_t, struct open_file *);
-static int block_map(struct open_file *, daddr_t, daddr_t *);
+static int block_map(struct open_file *, ufs2_daddr_t, ufs2_daddr_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int buf_write_file(struct open_file *, char *, size_t *);
static int search_directory(char *, struct open_file *, ino_t *);
-#ifdef COMPAT_UFS
-static void ffs_oldfscompat(struct fs *);
-#endif
/*
* Read a new inode into a file structure.
@@ -162,12 +174,12 @@ read_inode(inumber, f)
goto out;
}
- {
- struct dinode *dp;
-
- dp = (struct dinode *)buf;
- fp->f_di = dp[ino_to_fsbo(fs, inumber)];
- }
+ if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
+ fp->f_di.di1 = ((struct ufs1_dinode *)buf)
+ [ino_to_fsbo(fs, inumber)];
+ else
+ fp->f_di.di2 = ((struct ufs2_dinode *)buf)
+ [ino_to_fsbo(fs, inumber)];
/*
* Clear out the old buffers
@@ -191,15 +203,14 @@ out:
static int
block_map(f, file_block, disk_block_p)
struct open_file *f;
- daddr_t file_block;
- daddr_t *disk_block_p; /* out */
+ ufs2_daddr_t file_block;
+ ufs2_daddr_t *disk_block_p; /* out */
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
int level;
int idx;
- daddr_t ind_block_num;
- u_int32_t *ind_p;
+ ufs2_daddr_t ind_block_num;
int rc;
/*
@@ -227,7 +238,7 @@ block_map(f, file_block, disk_block_p)
if (file_block < NDADDR) {
/* Direct block. */
- *disk_block_p = fp->f_di.di_db[file_block];
+ *disk_block_p = DIP(fp, di_db[file_block]);
return (0);
}
@@ -249,7 +260,7 @@ block_map(f, file_block, disk_block_p)
return (EFBIG);
}
- ind_block_num = fp->f_di.di_ib[level];
+ ind_block_num = DIP(fp, di_ib[level]);
for (; level >= 0; level--) {
if (ind_block_num == 0) {
@@ -274,15 +285,16 @@ block_map(f, file_block, disk_block_p)
fp->f_blkno[level] = ind_block_num;
}
- ind_p = (u_int32_t *)fp->f_blk[level];
-
if (level > 0) {
idx = file_block / fp->f_nindir[level - 1];
file_block %= fp->f_nindir[level - 1];
} else
idx = file_block;
- ind_block_num = ind_p[idx];
+ if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
+ ind_block_num = ((ufs1_daddr_t *)fp->f_blk[level])[idx];
+ else
+ ind_block_num = ((ufs2_daddr_t *)fp->f_blk[level])[idx];
}
*disk_block_p = ind_block_num;
@@ -302,8 +314,8 @@ buf_write_file(f, buf_p, size_p)
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
- daddr_t file_block;
- daddr_t disk_block;
+ ufs_lbn_t file_block;
+ ufs2_daddr_t disk_block;
size_t block_size;
int rc;
@@ -312,21 +324,22 @@ buf_write_file(f, buf_p, size_p)
*/
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
- block_size = dblksize(fs, &fp->f_di, file_block);
+ block_size = sblksize(fs, DIP(fp, di_size), file_block);
rc = block_map(f, file_block, &disk_block);
if (rc)
return (rc);
if (disk_block == 0)
- return (EFBIG); /* Because we can't allocate space on the drive */
+ /* Because we can't allocate space on the drive */
+ return (EFBIG);
/*
* Truncate buffer at end of file, and at the end of
* this block.
*/
- if (*size_p > fp->f_di.di_size - fp->f_seekp)
- *size_p = fp->f_di.di_size - fp->f_seekp;
+ if (*size_p > DIP(fp, di_size) - fp->f_seekp)
+ *size_p = DIP(fp, di_size) - fp->f_seekp;
if (*size_p > block_size - off)
*size_p = block_size - off;
@@ -353,7 +366,7 @@ buf_write_file(f, buf_p, size_p)
/*
* Copy the user data into the cached block.
*/
- bcopy(buf_p,fp->f_buf + off,*size_p);
+ bcopy(buf_p, fp->f_buf + off, *size_p);
/*
* Write the block out to storage.
@@ -379,14 +392,14 @@ buf_read_file(f, buf_p, size_p)
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
- daddr_t file_block;
- daddr_t disk_block;
+ ufs_lbn_t file_block;
+ ufs2_daddr_t disk_block;
size_t block_size;
int rc;
off = blkoff(fs, fp->f_seekp);
file_block = lblkno(fs, fp->f_seekp);
- block_size = dblksize(fs, &fp->f_di, file_block);
+ block_size = sblksize(fs, DIP(fp, di_size), file_block);
if (file_block != fp->f_buf_blkno) {
if (fp->f_buf == (char *)0)
@@ -422,8 +435,8 @@ buf_read_file(f, buf_p, size_p)
/*
* But truncate buffer at end of file.
*/
- if (*size_p > fp->f_di.di_size - fp->f_seekp)
- *size_p = fp->f_di.di_size - fp->f_seekp;
+ if (*size_p > DIP(fp, di_size) - fp->f_seekp)
+ *size_p = DIP(fp, di_size) - fp->f_seekp;
return (0);
}
@@ -449,7 +462,7 @@ search_directory(name, f, inumber_p)
length = strlen(name);
fp->f_seekp = 0;
- while (fp->f_seekp < fp->f_di.di_size) {
+ while (fp->f_seekp < DIP(fp, di_size)) {
rc = buf_read_file(f, &buf, &buf_size);
if (rc)
return (rc);
@@ -479,6 +492,8 @@ search_directory(name, f, inumber_p)
return (ENOENT);
}
+static int sblock_try[] = SBLOCKSEARCH;
+
/*
* Open a file.
*/
@@ -492,7 +507,7 @@ ufs_open(upath, f)
ino_t inumber, parent_inumber;
struct file *fp;
struct fs *fs;
- int rc;
+ int i, rc;
size_t buf_size;
int nlinks = 0;
char namebuf[MAXPATHLEN+1];
@@ -505,28 +520,35 @@ ufs_open(upath, f)
f->f_fsdata = (void *)fp;
/* allocate space and read super block */
- fs = malloc(SBSIZE);
+ fs = malloc(SBLOCKSIZE);
fp->f_fs = fs;
twiddle();
- rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
- SBLOCK, SBSIZE, (char *)fs, &buf_size);
- if (rc)
- goto out;
-
- if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
- fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) {
+ /*
+ * Try reading the superblock in each of its possible locations.
+ */
+ for (i = 0; sblock_try[i] != -1; i++) {
+ rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
+ sblock_try[i] / DEV_BSIZE, SBLOCKSIZE,
+ (char *)fs, &buf_size);
+ if (rc)
+ goto out;
+ if ((fs->fs_magic == FS_UFS1_MAGIC ||
+ (fs->fs_magic == FS_UFS2_MAGIC &&
+ fs->fs_sblockloc == numfrags(fs, sblock_try[i]))) &&
+ buf_size == SBLOCKSIZE &&
+ fs->fs_bsize <= MAXBSIZE &&
+ fs->fs_bsize >= sizeof(struct fs))
+ break;
+ }
+ if (sblock_try[i] == -1) {
rc = EINVAL;
goto out;
}
-#ifdef COMPAT_UFS
- ffs_oldfscompat(fs);
-#endif
-
/*
* Calculate indirect block levels.
*/
{
- int mult;
+ ufs2_daddr_t mult;
int level;
mult = 1;
@@ -558,7 +580,7 @@ ufs_open(upath, f)
/*
* Check that current node is a directory.
*/
- if ((fp->f_di.di_mode & IFMT) != IFDIR) {
+ if ((DIP(fp, di_mode) & IFMT) != IFDIR) {
rc = ENOTDIR;
goto out;
}
@@ -600,8 +622,8 @@ ufs_open(upath, f)
/*
* Check for symbolic link.
*/
- if ((fp->f_di.di_mode & IFMT) == IFLNK) {
- int link_len = fp->f_di.di_size;
+ if ((DIP(fp, di_mode) & IFMT) == IFLNK) {
+ int link_len = DIP(fp, di_size);
int len;
len = strlen(cp);
@@ -615,19 +637,22 @@ ufs_open(upath, f)
bcopy(cp, &namebuf[link_len], len + 1);
if (link_len < fs->fs_maxsymlinklen) {
- bcopy(fp->f_di.di_shortlink, namebuf,
- (unsigned) link_len);
+ if (fp->f_fs->fs_magic == FS_UFS1_MAGIC)
+ cp = (caddr_t)(fp->f_di.di1.di_db);
+ else
+ cp = (caddr_t)(fp->f_di.di2.di_db);
+ bcopy(cp, namebuf, (unsigned) link_len);
} else {
/*
* Read file for symbolic link
*/
size_t buf_size;
- daddr_t disk_block;
+ ufs2_daddr_t disk_block;
struct fs *fs = fp->f_fs;
if (!buf)
buf = malloc(fs->fs_bsize);
- rc = block_map(f, (daddr_t)0, &disk_block);
+ rc = block_map(f, (ufs2_daddr_t)0, &disk_block);
if (rc)
goto out;
@@ -715,7 +740,7 @@ ufs_read(f, start, size, resid)
char *addr = start;
while (size != 0) {
- if (fp->f_seekp >= fp->f_di.di_size)
+ if (fp->f_seekp >= DIP(fp, di_size))
break;
rc = buf_read_file(f, &buf, &buf_size);
@@ -756,7 +781,7 @@ ufs_write(f, start, size, resid)
csize = size;
while ((size != 0) && (csize != 0)) {
- if (fp->f_seekp >= fp->f_di.di_size)
+ if (fp->f_seekp >= DIP(fp, di_size))
break;
if (csize >= 512) csize = 512; /* XXX */
@@ -790,7 +815,7 @@ ufs_seek(f, offset, where)
fp->f_seekp += offset;
break;
case SEEK_END:
- fp->f_seekp = fp->f_di.di_size - offset;
+ fp->f_seekp = DIP(fp, di_size) - offset;
break;
default:
return (-1);
@@ -806,10 +831,10 @@ ufs_stat(f, sb)
struct file *fp = (struct file *)f->f_fsdata;
/* only important stuff */
- sb->st_mode = fp->f_di.di_mode;
- sb->st_uid = fp->f_di.di_uid;
- sb->st_gid = fp->f_di.di_gid;
- sb->st_size = fp->f_di.di_size;
+ sb->st_mode = DIP(fp, di_mode);
+ sb->st_uid = DIP(fp, di_uid);
+ sb->st_gid = DIP(fp, di_gid);
+ sb->st_size = DIP(fp, di_size);
return (0);
}
@@ -826,7 +851,7 @@ ufs_readdir(struct open_file *f, struct dirent *d)
* assume that a directory entry will not be split across blocks
*/
again:
- if (fp->f_seekp >= fp->f_di.di_size)
+ if (fp->f_seekp >= DIP(fp, di_size))
return (ENOENT);
error = buf_read_file(f, &buf, &buf_size);
if (error)
@@ -839,33 +864,3 @@ again:
strcpy(d->d_name, dp->d_name);
return (0);
}
-
-#ifdef COMPAT_UFS
-/*
- * Sanity checks for old file systems.
- *
- * XXX - goes away some day.
- */
-static void
-ffs_oldfscompat(fs)
- struct fs *fs;
-{
- int i;
-
- fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
- fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
- if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
- fs->fs_nrpos = 8; /* XXX */
- if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
- quad_t sizepb = fs->fs_bsize; /* XXX */
- /* XXX */
- fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
- for (i = 0; i < NIADDR; i++) { /* XXX */
- sizepb *= NINDIR(fs); /* XXX */
- fs->fs_maxfilesize += sizepb; /* XXX */
- } /* XXX */
- fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
- fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
- } /* XXX */
-}
-#endif
OpenPOWER on IntegriCloud