ufs2.c 16 KB

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