1 /* $OpenBSD: ufs.c,v 1.27 2019/08/03 15:22:17 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>
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 #include <lib/libkern/libkern.h>
73
74 #include "stand.h"
75 #include "ufs.h"
76
77 /*
78 * In-core open file.
79 */
80 struct file {
81 off_t f_seekp; /* seek pointer */
82 struct fs *f_fs; /* pointer to super-block */
83 struct ufs1_dinode f_di; /* copy of on-disk inode */
84 ufsino_t f_ino; /* our inode number */
85 int f_nindir[NIADDR];
86 /* number of blocks mapped by
87 indirect block at level i */
88 char *f_blk[NIADDR]; /* buffer for indirect block at
89 level i */
90 size_t f_blksize[NIADDR];
91 /* size of buffer */
92 daddr32_t f_blkno[NIADDR];/* disk address of block in buffer */
93 char *f_buf; /* buffer for data block */
94 size_t f_buf_size; /* size of data block */
95 daddr32_t f_buf_blkno; /* block number of data block */
96 };
97
98 static int read_inode(ufsino_t, struct open_file *);
99 static int chmod_inode(ufsino_t, struct open_file *, mode_t);
100 static int block_map(struct open_file *, daddr32_t, daddr32_t *);
101 static int buf_read_file(struct open_file *, char **, size_t *);
102 static int search_directory(char *, struct open_file *, ufsino_t *);
103 static int ufs_close_internal(struct file *);
104 #ifdef COMPAT_UFS
105 static void ffs_oldfscompat(struct fs *);
106 #endif
107
108 /*
109 * Read a new inode into a file structure.
110 */
111 static int
read_inode(ufsino_t inumber,struct open_file * f)112 read_inode(ufsino_t inumber, struct open_file *f)
113 {
114 struct file *fp = (struct file *)f->f_fsdata;
115 struct fs *fs = fp->f_fs;
116 char *buf;
117 size_t rsize;
118 int rc;
119
120 /*
121 * Read inode and save it.
122 */
123 buf = alloc(fs->fs_bsize);
124 twiddle();
125 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
126 fsbtodb(fs, (daddr32_t)ino_to_fsba(fs, inumber)), fs->fs_bsize,
127 buf, &rsize);
128 if (rc)
129 goto out;
130 if (rsize != (size_t)fs->fs_bsize) {
131 rc = EIO;
132 goto out;
133 }
134
135 {
136 struct ufs1_dinode *dp;
137
138 dp = (struct ufs1_dinode *)buf;
139 fp->f_di = dp[ino_to_fsbo(fs, inumber)];
140 }
141
142 /*
143 * Clear out the old buffers
144 */
145 {
146 int level;
147
148 for (level = 0; level < NIADDR; level++)
149 fp->f_blkno[level] = -1;
150 fp->f_buf_blkno = -1;
151 fp->f_seekp = 0;
152 }
153 out:
154 free(buf, fs->fs_bsize);
155 return (rc);
156 }
157
158 /*
159 * Read a new inode into a file structure.
160 */
161 static int
chmod_inode(ufsino_t inumber,struct open_file * f,mode_t mode)162 chmod_inode(ufsino_t inumber, struct open_file *f, mode_t mode)
163 {
164 struct file *fp = (struct file *)f->f_fsdata;
165 struct fs *fs = fp->f_fs;
166 char *buf;
167 size_t rsize;
168 int rc;
169
170 /*
171 * Read inode and save it.
172 */
173 buf = alloc(fs->fs_bsize);
174 twiddle();
175 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
176 fsbtodb(fs, (daddr32_t)ino_to_fsba(fs, inumber)), fs->fs_bsize,
177 buf, &rsize);
178 if (rc)
179 goto out;
180 if (rsize != (size_t)fs->fs_bsize) {
181 rc = EIO;
182 goto out;
183 }
184
185 {
186 struct ufs1_dinode *dp;
187
188 dp = &((struct ufs1_dinode *)buf)[ino_to_fsbo(fs, inumber)];
189 dp->di_mode = mode;
190 }
191
192 twiddle();
193 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_WRITE,
194 fsbtodb(fs, (daddr32_t)ino_to_fsba(fs, inumber)), fs->fs_bsize,
195 buf, NULL);
196
197 out:
198 free(buf, fs->fs_bsize);
199 return (rc);
200 }
201
202 /*
203 * Given an offset in a file, find the disk block number that
204 * contains that block.
205 */
206 static int
block_map(struct open_file * f,daddr32_t file_block,daddr32_t * disk_block_p)207 block_map(struct open_file *f, daddr32_t file_block, daddr32_t *disk_block_p)
208 {
209 struct file *fp = (struct file *)f->f_fsdata;
210 daddr32_t ind_block_num, *ind_p;
211 struct fs *fs = fp->f_fs;
212 int level, idx, rc;
213
214 /*
215 * Index structure of an inode:
216 *
217 * di_db[0..NDADDR-1] hold block numbers for blocks
218 * 0..NDADDR-1
219 *
220 * di_ib[0] index block 0 is the single indirect block
221 * holds block numbers for blocks
222 * NDADDR .. NDADDR + NINDIR(fs)-1
223 *
224 * di_ib[1] index block 1 is the double indirect block
225 * holds block numbers for INDEX blocks for blocks
226 * NDADDR + NINDIR(fs) ..
227 * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
228 *
229 * di_ib[2] index block 2 is the triple indirect block
230 * holds block numbers for double-indirect
231 * blocks for blocks
232 * NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
233 * NDADDR + NINDIR(fs) + NINDIR(fs)**2
234 * + NINDIR(fs)**3 - 1
235 */
236
237 if (file_block < NDADDR) {
238 /* Direct block. */
239 *disk_block_p = fp->f_di.di_db[file_block];
240 return (0);
241 }
242
243 file_block -= NDADDR;
244
245 /*
246 * nindir[0] = NINDIR
247 * nindir[1] = NINDIR**2
248 * nindir[2] = NINDIR**3
249 * etc
250 */
251 for (level = 0; level < NIADDR; level++) {
252 if (file_block < fp->f_nindir[level])
253 break;
254 file_block -= fp->f_nindir[level];
255 }
256 if (level == NIADDR) {
257 /* Block number too high */
258 return (EFBIG);
259 }
260
261 ind_block_num = fp->f_di.di_ib[level];
262
263 for (; level >= 0; level--) {
264 if (ind_block_num == 0) {
265 *disk_block_p = 0; /* missing */
266 return (0);
267 }
268
269 if (fp->f_blkno[level] != ind_block_num) {
270 if (fp->f_blk[level] == NULL)
271 fp->f_blk[level] =
272 alloc(fs->fs_bsize);
273 twiddle();
274 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
275 fsbtodb(fp->f_fs, ind_block_num), fs->fs_bsize,
276 fp->f_blk[level], &fp->f_blksize[level]);
277 if (rc)
278 return (rc);
279 if (fp->f_blksize[level] != (size_t)fs->fs_bsize)
280 return (EIO);
281 fp->f_blkno[level] = ind_block_num;
282 }
283
284 ind_p = (daddr32_t *)fp->f_blk[level];
285
286 if (level > 0) {
287 idx = file_block / fp->f_nindir[level - 1];
288 file_block %= fp->f_nindir[level - 1];
289 } else
290 idx = file_block;
291
292 ind_block_num = ind_p[idx];
293 }
294
295 *disk_block_p = ind_block_num;
296 return (0);
297 }
298
299 /*
300 * Read a portion of a file into an internal buffer. Return
301 * the location in the buffer and the amount in the buffer.
302 */
303 static int
buf_read_file(struct open_file * f,char ** buf_p,size_t * size_p)304 buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
305 {
306 struct file *fp = (struct file *)f->f_fsdata;
307 struct fs *fs = fp->f_fs;
308 daddr32_t file_block, disk_block;
309 size_t block_size;
310 long off;
311 int rc;
312
313 off = blkoff(fs, fp->f_seekp);
314 file_block = lblkno(fs, fp->f_seekp);
315 block_size = dblksize(fs, &fp->f_di, (u_int64_t)file_block);
316
317 if (file_block != fp->f_buf_blkno) {
318 rc = block_map(f, file_block, &disk_block);
319 if (rc)
320 return (rc);
321
322 if (fp->f_buf == NULL)
323 fp->f_buf = alloc(fs->fs_bsize);
324
325 if (disk_block == 0) {
326 bzero(fp->f_buf, block_size);
327 fp->f_buf_size = block_size;
328 } else {
329 twiddle();
330 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
331 fsbtodb(fs, disk_block),
332 block_size, fp->f_buf, &fp->f_buf_size);
333 if (rc)
334 return (rc);
335 }
336
337 fp->f_buf_blkno = file_block;
338 }
339
340 /*
341 * Return address of byte in buffer corresponding to
342 * offset, and size of remainder of buffer after that
343 * byte.
344 */
345 *buf_p = fp->f_buf + off;
346 *size_p = block_size - off;
347
348 /*
349 * But truncate buffer at end of file.
350 */
351 if (*size_p > fp->f_di.di_size - fp->f_seekp)
352 *size_p = fp->f_di.di_size - fp->f_seekp;
353
354 return (0);
355 }
356
357 /*
358 * Search a directory for a name and return its
359 * i_number.
360 */
361 static int
search_directory(char * name,struct open_file * f,ufsino_t * inumber_p)362 search_directory(char *name, struct open_file *f, ufsino_t *inumber_p)
363 {
364 struct file *fp = (struct file *)f->f_fsdata;
365 int namlen, length, rc;
366 struct direct *dp, *edp;
367 size_t buf_size;
368 char *buf;
369
370 length = strlen(name);
371
372 fp->f_seekp = 0;
373 while ((u_int64_t)fp->f_seekp < fp->f_di.di_size) {
374 rc = buf_read_file(f, &buf, &buf_size);
375 if (rc)
376 return (rc);
377
378 dp = (struct direct *)buf;
379 edp = (struct direct *)(buf + buf_size);
380 while (dp < edp) {
381 if (dp->d_ino == 0)
382 goto next;
383 #if BYTE_ORDER == LITTLE_ENDIAN
384 if (fp->f_fs->fs_maxsymlinklen <= 0)
385 namlen = dp->d_type;
386 else
387 #endif
388 namlen = dp->d_namlen;
389 if (namlen == length &&
390 !strcmp(name, dp->d_name)) {
391 /* found entry */
392 *inumber_p = dp->d_ino;
393 return (0);
394 }
395 next:
396 dp = (struct direct *)((char *)dp + dp->d_reclen);
397 }
398 fp->f_seekp += buf_size;
399 }
400 return (ENOENT);
401 }
402
403 /*
404 * Open a file.
405 */
406 int
ufs_open(char * path,struct open_file * f)407 ufs_open(char *path, struct open_file *f)
408 {
409 char namebuf[MAXPATHLEN+1], *cp, *ncp, *buf = NULL;
410 ufsino_t inumber, parent_inumber;
411 int rc, c, nlinks = 0;
412 struct file *fp;
413 size_t buf_size;
414 struct fs *fs;
415
416 /* allocate file system specific data structure */
417 fp = alloc(sizeof(struct file));
418 bzero(fp, sizeof(struct file));
419 f->f_fsdata = (void *)fp;
420
421 /* allocate space and read super block */
422 fs = alloc(SBSIZE);
423 fp->f_fs = fs;
424 twiddle();
425 rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ,
426 SBLOCK, SBSIZE, (char *)fs, &buf_size);
427 if (rc)
428 goto out;
429
430 if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC ||
431 (size_t)fs->fs_bsize > MAXBSIZE ||
432 (size_t)fs->fs_bsize < sizeof(struct fs)) {
433 rc = EINVAL;
434 goto out;
435 }
436 #ifdef COMPAT_UFS
437 ffs_oldfscompat(fs);
438 #endif
439
440 /*
441 * Calculate indirect block levels.
442 */
443 {
444 int mult;
445 int level;
446
447 mult = 1;
448 for (level = 0; level < NIADDR; level++) {
449 mult *= NINDIR(fs);
450 fp->f_nindir[level] = mult;
451 }
452 }
453
454 inumber = ROOTINO;
455 if ((rc = read_inode(inumber, f)) != 0)
456 goto out;
457
458 cp = path;
459 while (*cp) {
460
461 /*
462 * Remove extra separators
463 */
464 while (*cp == '/')
465 cp++;
466 if (*cp == '\0')
467 break;
468
469 /*
470 * Check that current node is a directory.
471 */
472 if ((fp->f_di.di_mode & IFMT) != IFDIR) {
473 rc = ENOTDIR;
474 goto out;
475 }
476
477 /*
478 * Get next component of path name.
479 */
480 {
481 int len = 0;
482
483 ncp = cp;
484 while ((c = *cp) != '\0' && c != '/') {
485 if (++len > MAXNAMLEN) {
486 rc = ENOENT;
487 goto out;
488 }
489 cp++;
490 }
491 *cp = '\0';
492 }
493
494 /*
495 * Look up component in current directory.
496 * Save directory inumber in case we find a
497 * symbolic link.
498 */
499 parent_inumber = inumber;
500 rc = search_directory(ncp, f, &inumber);
501 *cp = c;
502 if (rc)
503 goto out;
504
505 /*
506 * Open next component.
507 */
508 if ((rc = read_inode(inumber, f)) != 0)
509 goto out;
510
511 /*
512 * Check for symbolic link.
513 */
514 if ((fp->f_di.di_mode & IFMT) == IFLNK) {
515 u_int64_t link_len = fp->f_di.di_size;
516 size_t len;
517
518 len = strlen(cp);
519
520 if (link_len + len > MAXPATHLEN ||
521 ++nlinks > MAXSYMLINKS) {
522 rc = ENOENT;
523 goto out;
524 }
525
526 bcopy(cp, &namebuf[link_len], len + 1);
527
528 if (link_len < (u_int64_t)fs->fs_maxsymlinklen) {
529 bcopy(fp->f_di.di_shortlink, namebuf, link_len);
530 } else {
531 /*
532 * Read file for symbolic link
533 */
534 daddr32_t disk_block;
535 fs = fp->f_fs;
536
537 if (!buf)
538 buf = alloc(fs->fs_bsize);
539 rc = block_map(f, (daddr32_t)0, &disk_block);
540 if (rc)
541 goto out;
542
543 twiddle();
544 rc = (f->f_dev->dv_strategy)(f->f_devdata,
545 F_READ, fsbtodb(fs, disk_block),
546 fs->fs_bsize, buf, &buf_size);
547 if (rc)
548 goto out;
549
550 bcopy(buf, namebuf, link_len);
551 }
552
553 /*
554 * If relative pathname, restart at parent directory.
555 * If absolute pathname, restart at root.
556 */
557 cp = namebuf;
558 if (*cp != '/')
559 inumber = parent_inumber;
560 else
561 inumber = ROOTINO;
562
563 if ((rc = read_inode(inumber, f)) != 0)
564 goto out;
565 }
566 }
567
568 /*
569 * Found terminal component.
570 */
571 fp->f_ino = inumber;
572 rc = 0;
573 out:
574 if (buf)
575 free(buf, fs->fs_bsize);
576 if (rc)
577 (void)ufs_close_internal(fp);
578
579 return (rc);
580 }
581
582 int
ufs_close(struct open_file * f)583 ufs_close(struct open_file *f)
584 {
585 struct file *fp = (struct file *)f->f_fsdata;
586
587 f->f_fsdata = NULL;
588 if (fp == NULL)
589 return (0);
590
591 return (ufs_close_internal(fp));
592 }
593
594 static int
ufs_close_internal(struct file * fp)595 ufs_close_internal(struct file *fp)
596 {
597 int level;
598
599 for (level = 0; level < NIADDR; level++) {
600 if (fp->f_blk[level])
601 free(fp->f_blk[level], fp->f_fs->fs_bsize);
602 }
603 if (fp->f_buf)
604 free(fp->f_buf, fp->f_fs->fs_bsize);
605 free(fp->f_fs, SBSIZE);
606 free(fp, sizeof(struct file));
607 return (0);
608 }
609
610 /*
611 * Copy a portion of a file into kernel memory.
612 * Cross block boundaries when necessary.
613 */
614 int
ufs_read(struct open_file * f,void * start,size_t size,size_t * resid)615 ufs_read(struct open_file *f, void *start, size_t size, size_t *resid)
616 {
617 struct file *fp = (struct file *)f->f_fsdata;
618 char *buf, *addr = start;
619 size_t csize, buf_size;
620 int rc = 0;
621
622 while (size != 0) {
623 if ((u_int64_t)fp->f_seekp >= fp->f_di.di_size)
624 break;
625
626 rc = buf_read_file(f, &buf, &buf_size);
627 if (rc)
628 break;
629
630 csize = size;
631 if (csize > buf_size)
632 csize = buf_size;
633
634 bcopy(buf, addr, csize);
635
636 fp->f_seekp += csize;
637 addr += csize;
638 size -= csize;
639 }
640 if (resid)
641 *resid = size;
642 return (rc);
643 }
644
645 /*
646 * Not implemented.
647 */
648 int
ufs_write(struct open_file * f,void * start,size_t size,size_t * resid)649 ufs_write(struct open_file *f, void *start, size_t size, size_t *resid)
650 {
651
652 return (EROFS);
653 }
654
655 off_t
ufs_seek(struct open_file * f,off_t offset,int where)656 ufs_seek(struct open_file *f, off_t offset, int where)
657 {
658 struct file *fp = (struct file *)f->f_fsdata;
659
660 switch (where) {
661 case SEEK_SET:
662 fp->f_seekp = offset;
663 break;
664 case SEEK_CUR:
665 fp->f_seekp += offset;
666 break;
667 case SEEK_END:
668 fp->f_seekp = fp->f_di.di_size - offset;
669 break;
670 default:
671 return (-1);
672 }
673 return (fp->f_seekp);
674 }
675
676 int
ufs_stat(struct open_file * f,struct stat * sb)677 ufs_stat(struct open_file *f, struct stat *sb)
678 {
679 struct file *fp = (struct file *)f->f_fsdata;
680
681 /* only important stuff */
682 sb->st_mode = fp->f_di.di_mode;
683 sb->st_uid = fp->f_di.di_uid;
684 sb->st_gid = fp->f_di.di_gid;
685 sb->st_size = fp->f_di.di_size;
686 return (0);
687 }
688
689 int
ufs_fchmod(struct open_file * f,mode_t mode)690 ufs_fchmod(struct open_file *f, mode_t mode)
691 {
692 struct file *fp = (struct file *)f->f_fsdata;
693
694 return chmod_inode(fp->f_ino, f, mode);
695 }
696
697 #ifndef NO_READDIR
698 int
ufs_readdir(struct open_file * f,char * name)699 ufs_readdir(struct open_file *f, char *name)
700 {
701 struct file *fp = (struct file *)f->f_fsdata;
702 struct direct *dp, *edp;
703 size_t buf_size;
704 int rc, namlen;
705 char *buf;
706
707 if (name == NULL)
708 fp->f_seekp = 0;
709 else {
710 /* end of dir */
711 if ((u_int64_t)fp->f_seekp >= fp->f_di.di_size) {
712 *name = '\0';
713 return -1;
714 }
715
716 do {
717 if ((rc = buf_read_file(f, &buf, &buf_size)) != 0)
718 return rc;
719
720 dp = (struct direct *)buf;
721 edp = (struct direct *)(buf + buf_size);
722 while (dp < edp && dp->d_ino == 0)
723 dp = (struct direct *)((char *)dp + dp->d_reclen);
724 fp->f_seekp += buf_size -
725 ((u_int8_t *)edp - (u_int8_t *)dp);
726 } while (dp >= edp);
727
728 #if BYTE_ORDER == LITTLE_ENDIAN
729 if (fp->f_fs->fs_maxsymlinklen <= 0)
730 namlen = dp->d_type;
731 else
732 #endif
733 namlen = dp->d_namlen;
734 strncpy(name, dp->d_name, namlen + 1);
735
736 fp->f_seekp += dp->d_reclen;
737 }
738
739 return 0;
740 }
741 #endif
742
743 #ifdef COMPAT_UFS
744 /*
745 * Sanity checks for old file systems.
746 *
747 * XXX - goes away some day.
748 */
749 static void
ffs_oldfscompat(struct fs * fs)750 ffs_oldfscompat(struct fs *fs)
751 {
752 int i;
753
754 fs->fs_npsect = max(fs->fs_npsect, fs->fs_nsect); /* XXX */
755 fs->fs_interleave = max(fs->fs_interleave, 1); /* XXX */
756 if (fs->fs_postblformat == FS_42POSTBLFMT) /* XXX */
757 fs->fs_nrpos = 8; /* XXX */
758 if (fs->fs_inodefmt < FS_44INODEFMT) { /* XXX */
759 quad_t sizepb = fs->fs_bsize; /* XXX */
760 /* XXX */
761 fs->fs_maxfilesize = fs->fs_bsize * NDADDR - 1; /* XXX */
762 for (i = 0; i < NIADDR; i++) { /* XXX */
763 sizepb *= NINDIR(fs); /* XXX */
764 fs->fs_maxfilesize += sizepb; /* XXX */
765 } /* XXX */
766 fs->fs_qbmask = ~fs->fs_bmask; /* XXX */
767 fs->fs_qfmask = ~fs->fs_fmask; /* XXX */
768 } /* XXX */
769 }
770 #endif
771