GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/vmd/ufs.c Lines: 0 219 0.0 %
Date: 2017-11-07 Branches: 0 140 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: ufs.c,v 1.5 2017/08/29 21:10:20 deraadt Exp $	*/
2
/*	$NetBSD: ufs.c,v 1.16 1996/09/30 16:01:22 ws Exp $	*/
3
4
/*-
5
 * Copyright (c) 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * This code is derived from software contributed to Berkeley by
9
 * The Mach Operating System project at Carnegie-Mellon University.
10
 *
11
 * Redistribution and use in source and binary forms, with or without
12
 * modification, are permitted provided that the following conditions
13
 * are met:
14
 * 1. Redistributions of source code must retain the above copyright
15
 *    notice, this list of conditions and the following disclaimer.
16
 * 2. Redistributions in binary form must reproduce the above copyright
17
 *    notice, this list of conditions and the following disclaimer in the
18
 *    documentation and/or other materials provided with the distribution.
19
 * 3. Neither the name of the University nor the names of its contributors
20
 *    may be used to endorse or promote products derived from this software
21
 *    without specific prior written permission.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 *
35
 *
36
 * Copyright (c) 1990, 1991 Carnegie Mellon University
37
 * All Rights Reserved.
38
 *
39
 * Author: David Golub
40
 *
41
 * Permission to use, copy, modify and distribute this software and its
42
 * documentation is hereby granted, provided that both the copyright
43
 * notice and this permission notice appear in all copies of the
44
 * software, derivative works or modified versions, and any portions
45
 * thereof, and that both notices appear in supporting documentation.
46
 *
47
 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
48
 * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
49
 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
50
 *
51
 * Carnegie Mellon requests users of this software to return to
52
 *
53
 *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
54
 *  School of Computer Science
55
 *  Carnegie Mellon University
56
 *  Pittsburgh PA 15213-3890
57
 *
58
 * any improvements or extensions that they make and grant Carnegie the
59
 * rights to redistribute these changes.
60
 */
61
62
/*
63
 *	Stand-alone file reading package.
64
 */
65
66
#include <sys/param.h>	/* DEV_BSIZE MAXBSIZE */
67
#include <sys/time.h>
68
#include <sys/stat.h>
69
#include <ufs/ffs/fs.h>
70
#include <ufs/ufs/dinode.h>
71
#include <ufs/ufs/dir.h>
72
73
#include <limits.h>
74
75
#include "vmboot.h"
76
77
/* Used in the kernel by libsa */
78
#define alloc		malloc
79
#define free(_p, _n)	free(_p)
80
#define twiddle()	do { } while(0)
81
#define NO_READDIR	1
82
83
/*
84
 * In-core open file.
85
 */
86
struct file {
87
	off_t		f_seekp;	/* seek pointer */
88
	struct fs	*f_fs;		/* pointer to super-block */
89
	struct ufs1_dinode	f_di;		/* copy of on-disk inode */
90
	int		f_nindir[NIADDR];
91
					/* number of blocks mapped by
92
					   indirect block at level i */
93
	char		*f_blk[NIADDR];	/* buffer for indirect block at
94
					   level i */
95
	size_t		f_blksize[NIADDR];
96
					/* size of buffer */
97
	daddr32_t	f_blkno[NIADDR];/* disk address of block in buffer */
98
	char		*f_buf;		/* buffer for data block */
99
	size_t		f_buf_size;	/* size of data block */
100
	daddr32_t	f_buf_blkno;	/* block number of data block */
101
};
102
103
static int	read_inode(ufsino_t, struct open_file *);
104
static int	block_map(struct open_file *, daddr32_t, daddr32_t *);
105
static int	buf_read_file(struct open_file *, char **, size_t *);
106
static int	search_directory(char *, struct open_file *, ufsino_t *);
107
static int	ufs_close_internal(struct file *);
108
#ifdef COMPAT_UFS
109
static void	ffs_oldfscompat(struct fs *);
110
#endif
111
112
/*
113
 * Read a new inode into a file structure.
114
 */
115
static int
116
read_inode(ufsino_t inumber, struct open_file *f)
117
{
118
	struct file *fp = (struct file *)f->f_fsdata;
119
	struct fs *fs = fp->f_fs;
120
	char *buf;
121
	size_t rsize;
122
	int rc;
123
124
	/*
125
	 * Read inode and save it.
126
	 */
127
	buf = alloc(fs->fs_bsize);
128
	twiddle();
129
	rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
130
	    fsbtodb(fs, (daddr32_t)ino_to_fsba(fs, inumber)), fs->fs_bsize,
131
	    buf, &rsize);
132
	if (rc)
133
		goto out;
134
	if (rsize != (size_t)fs->fs_bsize) {
135
		rc = EIO;
136
		goto out;
137
	}
138
139
	{
140
		struct ufs1_dinode *dp;
141
142
		dp = (struct ufs1_dinode *)buf;
143
		fp->f_di = dp[ino_to_fsbo(fs, inumber)];
144
	}
145
146
	/*
147
	 * Clear out the old buffers
148
	 */
149
	{
150
		int level;
151
152
		for (level = 0; level < NIADDR; level++)
153
			fp->f_blkno[level] = -1;
154
		fp->f_buf_blkno = -1;
155
		fp->f_seekp = 0;
156
	}
157
out:
158
	free(buf, fs->fs_bsize);
159
	return (rc);
160
}
161
162
/*
163
 * Given an offset in a file, find the disk block number that
164
 * contains that block.
165
 */
166
static int
167
block_map(struct open_file *f, daddr32_t file_block, daddr32_t *disk_block_p)
168
{
169
	struct file *fp = (struct file *)f->f_fsdata;
170
	daddr32_t ind_block_num, *ind_p;
171
	struct fs *fs = fp->f_fs;
172
	int level, idx, rc;
173
174
	/*
175
	 * Index structure of an inode:
176
	 *
177
	 * di_db[0..NDADDR-1]	hold block numbers for blocks
178
	 *			0..NDADDR-1
179
	 *
180
	 * di_ib[0]		index block 0 is the single indirect block
181
	 *			holds block numbers for blocks
182
	 *			NDADDR .. NDADDR + NINDIR(fs)-1
183
	 *
184
	 * di_ib[1]		index block 1 is the double indirect block
185
	 *			holds block numbers for INDEX blocks for blocks
186
	 *			NDADDR + NINDIR(fs) ..
187
	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
188
	 *
189
	 * di_ib[2]		index block 2 is the triple indirect block
190
	 *			holds block numbers for double-indirect
191
	 *			blocks for blocks
192
	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
193
	 *			NDADDR + NINDIR(fs) + NINDIR(fs)**2
194
	 *				+ NINDIR(fs)**3 - 1
195
	 */
196
197
	if (file_block < NDADDR) {
198
		/* Direct block. */
199
		*disk_block_p = fp->f_di.di_db[file_block];
200
		return (0);
201
	}
202
203
	file_block -= NDADDR;
204
205
	/*
206
	 * nindir[0] = NINDIR
207
	 * nindir[1] = NINDIR**2
208
	 * nindir[2] = NINDIR**3
209
	 *	etc
210
	 */
211
	for (level = 0; level < NIADDR; level++) {
212
		if (file_block < fp->f_nindir[level])
213
			break;
214
		file_block -= fp->f_nindir[level];
215
	}
216
	if (level == NIADDR) {
217
		/* Block number too high */
218
		return (EFBIG);
219
	}
220
221
	ind_block_num = fp->f_di.di_ib[level];
222
223
	for (; level >= 0; level--) {
224
		if (ind_block_num == 0) {
225
			*disk_block_p = 0;	/* missing */
226
			return (0);
227
		}
228
229
		if (fp->f_blkno[level] != ind_block_num) {
230
			if (fp->f_blk[level] == NULL)
231
				fp->f_blk[level] =
232
				    alloc(fs->fs_bsize);
233
			twiddle();
234
			rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
235
			    fsbtodb(fp->f_fs, ind_block_num), fs->fs_bsize,
236
			    fp->f_blk[level], &fp->f_blksize[level]);
237
			if (rc)
238
				return (rc);
239
			if (fp->f_blksize[level] != (size_t)fs->fs_bsize)
240
				return (EIO);
241
			fp->f_blkno[level] = ind_block_num;
242
		}
243
244
		ind_p = (daddr32_t *)fp->f_blk[level];
245
246
		if (level > 0) {
247
			idx = file_block / fp->f_nindir[level - 1];
248
			file_block %= fp->f_nindir[level - 1];
249
		} else
250
			idx = file_block;
251
252
		ind_block_num = ind_p[idx];
253
	}
254
255
	*disk_block_p = ind_block_num;
256
	return (0);
257
}
258
259
/*
260
 * Read a portion of a file into an internal buffer.  Return
261
 * the location in the buffer and the amount in the buffer.
262
 */
263
static int
264
buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
265
{
266
	struct file *fp = (struct file *)f->f_fsdata;
267
	struct fs *fs = fp->f_fs;
268
	daddr32_t file_block, disk_block;
269
	size_t block_size;
270
	long off;
271
	int rc;
272
273
	off = blkoff(fs, fp->f_seekp);
274
	file_block = lblkno(fs, fp->f_seekp);
275
	block_size = dblksize(fs, &fp->f_di, (u_int64_t)file_block);
276
277
	if (file_block != fp->f_buf_blkno) {
278
		rc = block_map(f, file_block, &disk_block);
279
		if (rc)
280
			return (rc);
281
282
		if (fp->f_buf == NULL)
283
			fp->f_buf = alloc(fs->fs_bsize);
284
285
		if (disk_block == 0) {
286
			bzero(fp->f_buf, block_size);
287
			fp->f_buf_size = block_size;
288
		} else {
289
			twiddle();
290
			rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
291
			    fsbtodb(fs, disk_block),
292
			    block_size, fp->f_buf, &fp->f_buf_size);
293
			if (rc)
294
				return (rc);
295
		}
296
297
		fp->f_buf_blkno = file_block;
298
	}
299
300
	/*
301
	 * Return address of byte in buffer corresponding to
302
	 * offset, and size of remainder of buffer after that
303
	 * byte.
304
	 */
305
	*buf_p = fp->f_buf + off;
306
	*size_p = block_size - off;
307
308
	/*
309
	 * But truncate buffer at end of file.
310
	 */
311
	if (*size_p > fp->f_di.di_size - fp->f_seekp)
312
		*size_p = fp->f_di.di_size - fp->f_seekp;
313
314
	return (0);
315
}
316
317
/*
318
 * Search a directory for a name and return its
319
 * i_number.
320
 */
321
static int
322
search_directory(char *name, struct open_file *f, ufsino_t *inumber_p)
323
{
324
	struct file *fp = (struct file *)f->f_fsdata;
325
	int namlen, length, rc;
326
	struct direct *dp, *edp;
327
	size_t buf_size;
328
	char *buf;
329
330
	length = strlen(name);
331
332
	fp->f_seekp = 0;
333
	while ((u_int64_t)fp->f_seekp < fp->f_di.di_size) {
334
		rc = buf_read_file(f, &buf, &buf_size);
335
		if (rc)
336
			return (rc);
337
338
		dp = (struct direct *)buf;
339
		edp = (struct direct *)(buf + buf_size);
340
		while (dp < edp) {
341
			if (dp->d_ino == 0)
342
				goto next;
343
#if BYTE_ORDER == LITTLE_ENDIAN
344
			if (fp->f_fs->fs_maxsymlinklen <= 0)
345
				namlen = dp->d_type;
346
			else
347
#endif
348
				namlen = dp->d_namlen;
349
			if (namlen == length &&
350
			    !strcmp(name, dp->d_name)) {
351
				/* found entry */
352
				*inumber_p = dp->d_ino;
353
				return (0);
354
			}
355
		next:
356
			dp = (struct direct *)((char *)dp + dp->d_reclen);
357
		}
358
		fp->f_seekp += buf_size;
359
	}
360
	return (ENOENT);
361
}
362
363
/*
364
 * Open a file.
365
 */
366
int
367
ufs_open(char *path, struct open_file *f)
368
{
369
	char namebuf[PATH_MAX+1], *cp, *ncp, *buf = NULL;
370
	ufsino_t inumber, parent_inumber;
371
	int rc, c, nlinks = 0;
372
	struct file *fp;
373
	size_t buf_size;
374
	struct fs *fs;
375
376
	/* allocate file system specific data structure */
377
	fp = alloc(sizeof(struct file));
378
	bzero(fp, sizeof(struct file));
379
	f->f_fsdata = (void *)fp;
380
381
	/* allocate space and read super block */
382
	fs = alloc(SBSIZE);
383
	fp->f_fs = fs;
384
	twiddle();
385
	rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
386
	    SBLOCK, SBSIZE, (char *)fs, &buf_size);
387
	if (rc)
388
		goto out;
389
390
	if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
391
	    (size_t)fs->fs_bsize > MAXBSIZE ||
392
	    (size_t)fs->fs_bsize < sizeof(struct fs)) {
393
		rc = EINVAL;
394
		goto out;
395
	}
396
#ifdef COMPAT_UFS
397
	ffs_oldfscompat(fs);
398
#endif
399
400
	/*
401
	 * Calculate indirect block levels.
402
	 */
403
	{
404
		int mult;
405
		int level;
406
407
		mult = 1;
408
		for (level = 0; level < NIADDR; level++) {
409
			mult *= NINDIR(fs);
410
			fp->f_nindir[level] = mult;
411
		}
412
	}
413
414
	inumber = ROOTINO;
415
	if ((rc = read_inode(inumber, f)) != 0)
416
		goto out;
417
418
	cp = path;
419
	while (*cp) {
420
421
		/*
422
		 * Remove extra separators
423
		 */
424
		while (*cp == '/')
425
			cp++;
426
		if (*cp == '\0')
427
			break;
428
429
		/*
430
		 * Check that current node is a directory.
431
		 */
432
		if ((fp->f_di.di_mode & IFMT) != IFDIR) {
433
			rc = ENOTDIR;
434
			goto out;
435
		}
436
437
		/*
438
		 * Get next component of path name.
439
		 */
440
		{
441
			int len = 0;
442
443
			ncp = cp;
444
			while ((c = *cp) != '\0' && c != '/') {
445
				if (++len > MAXNAMLEN) {
446
					rc = ENOENT;
447
					goto out;
448
				}
449
				cp++;
450
			}
451
			*cp = '\0';
452
		}
453
454
		/*
455
		 * Look up component in current directory.
456
		 * Save directory inumber in case we find a
457
		 * symbolic link.
458
		 */
459
		parent_inumber = inumber;
460
		rc = search_directory(ncp, f, &inumber);
461
		*cp = c;
462
		if (rc)
463
			goto out;
464
465
		/*
466
		 * Open next component.
467
		 */
468
		if ((rc = read_inode(inumber, f)) != 0)
469
			goto out;
470
471
		/*
472
		 * Check for symbolic link.
473
		 */
474
		if ((fp->f_di.di_mode & IFMT) == IFLNK) {
475
			u_int64_t link_len = fp->f_di.di_size;
476
			size_t len;
477
478
			len = strlen(cp);
479
480
			if (link_len + len > PATH_MAX ||
481
			    ++nlinks > SYMLOOP_MAX) {
482
				rc = ENOENT;
483
				goto out;
484
			}
485
486
			bcopy(cp, &namebuf[link_len], len + 1);
487
488
			if (link_len < (u_int64_t)fs->fs_maxsymlinklen) {
489
				bcopy(fp->f_di.di_shortlink, namebuf, link_len);
490
			} else {
491
				/*
492
				 * Read file for symbolic link
493
				 */
494
				daddr32_t disk_block;
495
				fs = fp->f_fs;
496
497
				if (!buf)
498
					buf = alloc(fs->fs_bsize);
499
				rc = block_map(f, (daddr32_t)0, &disk_block);
500
				if (rc)
501
					goto out;
502
503
				twiddle();
504
				rc = (f->f_dev->dv_strategy)(f->f_devdata,
505
				    F_READ, fsbtodb(fs, disk_block),
506
				    fs->fs_bsize, buf, &buf_size);
507
				if (rc)
508
					goto out;
509
510
				bcopy(buf, namebuf, link_len);
511
			}
512
513
			/*
514
			 * If relative pathname, restart at parent directory.
515
			 * If absolute pathname, restart at root.
516
			 */
517
			cp = namebuf;
518
			if (*cp != '/')
519
				inumber = parent_inumber;
520
			else
521
				inumber = ROOTINO;
522
523
			if ((rc = read_inode(inumber, f)) != 0)
524
				goto out;
525
		}
526
	}
527
528
	/*
529
	 * Found terminal component.
530
	 */
531
	rc = 0;
532
out:
533
	if (buf)
534
		free(buf, fs->fs_bsize);
535
	if (rc)
536
		(void)ufs_close_internal(fp);
537
538
	return (rc);
539
}
540
541
int
542
ufs_close(struct open_file *f)
543
{
544
	struct file *fp = (struct file *)f->f_fsdata;
545
546
	f->f_fsdata = NULL;
547
	if (fp == NULL)
548
		return (0);
549
550
	return (ufs_close_internal(fp));
551
}
552
553
static int
554
ufs_close_internal(struct file *fp)
555
{
556
	int level;
557
558
	for (level = 0; level < NIADDR; level++) {
559
		if (fp->f_blk[level])
560
			free(fp->f_blk[level], fp->f_fs->fs_bsize);
561
	}
562
	if (fp->f_buf)
563
		free(fp->f_buf, fp->f_fs->fs_bsize);
564
	free(fp->f_fs, SBSIZE);
565
	free(fp, sizeof(struct file));
566
	return (0);
567
}
568
569
/*
570
 * Copy a portion of a file into kernel memory.
571
 * Cross block boundaries when necessary.
572
 */
573
int
574
ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
575
{
576
	struct file *fp = (struct file *)f->f_fsdata;
577
	char *buf, *addr = start;
578
	size_t csize, buf_size;
579
	int rc = 0;
580
581
	while (size != 0) {
582
		if ((u_int64_t)fp->f_seekp >= fp->f_di.di_size)
583
			break;
584
585
		rc = buf_read_file(f, &buf, &buf_size);
586
		if (rc)
587
			break;
588
589
		csize = size;
590
		if (csize > buf_size)
591
			csize = buf_size;
592
593
		bcopy(buf, addr, csize);
594
595
		fp->f_seekp += csize;
596
		addr += csize;
597
		size -= csize;
598
	}
599
	if (resid)
600
		*resid = size;
601
	return (rc);
602
}
603
604
/*
605
 * Not implemented.
606
 */
607
int
608
ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
609
{
610
611
	return (EROFS);
612
}
613
614
off_t
615
ufs_seek(struct open_file *f, off_t offset, int where)
616
{
617
	struct file *fp = (struct file *)f->f_fsdata;
618
619
	switch (where) {
620
	case SEEK_SET:
621
		fp->f_seekp = offset;
622
		break;
623
	case SEEK_CUR:
624
		fp->f_seekp += offset;
625
		break;
626
	case SEEK_END:
627
		fp->f_seekp = fp->f_di.di_size - offset;
628
		break;
629
	default:
630
		return (-1);
631
	}
632
	return (fp->f_seekp);
633
}
634
635
int
636
ufs_stat(struct open_file *f, struct stat *sb)
637
{
638
	struct file *fp = (struct file *)f->f_fsdata;
639
640
	/* only important stuff */
641
	sb->st_mode = fp->f_di.di_mode;
642
	sb->st_uid = fp->f_di.di_uid;
643
	sb->st_gid = fp->f_di.di_gid;
644
	sb->st_size = fp->f_di.di_size;
645
	return (0);
646
}
647
648
#ifndef	NO_READDIR
649
int
650
ufs_readdir(struct open_file *f, char *name)
651
{
652
	struct file *fp = (struct file *)f->f_fsdata;
653
	struct direct *dp, *edp;
654
	size_t buf_size;
655
	int rc, namlen;
656
	char *buf;
657
658
	if (name == NULL)
659
		fp->f_seekp = 0;
660
	else {
661
			/* end of dir */
662
		if ((u_int64_t)fp->f_seekp >= fp->f_di.di_size) {
663
			*name = '\0';
664
			return -1;
665
		}
666
667
		do {
668
			if ((rc = buf_read_file(f, &buf, &buf_size)) != 0)
669
				return rc;
670
671
			dp = (struct direct *)buf;
672
			edp = (struct direct *)(buf + buf_size);
673
			while (dp < edp && dp->d_ino == 0)
674
				dp = (struct direct *)((char *)dp + dp->d_reclen);
675
			fp->f_seekp += buf_size -
676
			    ((u_int8_t *)edp - (u_int8_t *)dp);
677
		} while (dp >= edp);
678
679
#if BYTE_ORDER == LITTLE_ENDIAN
680
		if (fp->f_fs->fs_maxsymlinklen <= 0)
681
			namlen = dp->d_type;
682
		else
683
#endif
684
			namlen = dp->d_namlen;
685
		strncpy(name, dp->d_name, namlen + 1);
686
687
		fp->f_seekp += dp->d_reclen;
688
	}
689
690
	return 0;
691
}
692
#endif
693
694
#ifdef COMPAT_UFS
695
/*
696
 * Sanity checks for old file systems.
697
 *
698
 * XXX - goes away some day.
699
 */
700
static void
701
ffs_oldfscompat(struct fs *fs)
702
{
703
	int i;
704
705
	fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect);	/* XXX */
706
	fs->fs_interleave = max(fs->fs_interleave, 1);		/* XXX */
707
	if (fs->fs_postblformat == FS_42POSTBLFMT)		/* XXX */
708
		fs->fs_nrpos = 8;				/* XXX */
709
	if (fs->fs_inodefmt < FS_44INODEFMT) {			/* XXX */
710
		quad_t sizepb = fs->fs_bsize;			/* XXX */
711
								/* XXX */
712
		fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1;	/* XXX */
713
		for (i = 0; i < NIADDR; i++) {			/* XXX */
714
			sizepb *= NINDIR(fs);			/* XXX */
715
			fs->fs_maxfilesize += sizepb;		/* XXX */
716
		}						/* XXX */
717
		fs->fs_qbmask = ~fs->fs_bmask;			/* XXX */
718
		fs->fs_qfmask = ~fs->fs_fmask;			/* XXX */
719
	}							/* XXX */
720
}
721
#endif