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