1 /* $NetBSD: minixfs3.c,v 1.7 2014/03/20 03:13:18 christos Exp $ */
5 * Vrije Universiteit, Amsterdam, The Netherlands. All rights reserved.
7 * Author: Evgeniy Ivanov (based on libsa/ext2fs.c).
9 * This code is derived from src/sys/lib/libsa/ext2fs.c contributed to
10 * The NetBSD Foundation, see copyrights below.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
22 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
35 * Copyright (c) 1997 Manuel Bouyer.
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
47 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
48 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
49 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
50 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
51 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
52 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
53 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
55 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 * The Regents of the University of California. All rights reserved.
62 * This code is derived from software contributed to Berkeley by
63 * The Mach Operating System project at Carnegie-Mellon University.
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
68 * 1. Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer.
70 * 2. Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in the
72 * documentation and/or other materials provided with the distribution.
73 * 3. Neither the name of the University nor the names of its contributors
74 * may be used to endorse or promote products derived from this software
75 * without specific prior written permission.
77 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
78 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
79 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
80 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
81 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
82 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
83 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
84 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
85 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
86 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
90 * Copyright (c) 1990, 1991 Carnegie Mellon University
91 * All Rights Reserved.
95 * Permission to use, copy, modify and distribute this software and its
96 * documentation is hereby granted, provided that both the copyright
97 * notice and this permission notice appear in all copies of the
98 * software, derivative works or modified versions, and any portions
99 * thereof, and that both notices appear in supporting documentation.
101 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
102 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
103 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
105 * Carnegie Mellon requests users of this software to return to
107 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
108 * School of Computer Science
109 * Carnegie Mellon University
110 * Pittsburgh PA 15213-3890
112 * any improvements or extensions that they make and grant Carnegie the
113 * rights to redistribute these changes.
117 * Stand-alone file reading package for MFS file system.
120 #include <sys/param.h>
121 #include <sys/time.h>
123 #include <lib/libkern/libkern.h>
129 #include "minixfs3.h"
131 #if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
132 #define LIBSA_NO_FS_SYMLINK
135 #if defined(LIBSA_NO_TWIDDLE)
139 typedef uint32_t ino32_t
;
141 #define FSBTODB(fs, indp) MFS_FSBTODB(fs, indp)
145 * To avoid having a lot of filesystem-block sized buffers lurking (which
146 * could be 32k) we only keep a few entries of the indirect block map.
147 * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
148 * ~13 times pulling in a 6M kernel.
149 * The cache size must be smaller than the smallest filesystem block,
150 * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
152 #define LN2_IND_CACHE_SZ 6
153 #define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ)
154 #define IND_CACHE_MASK (IND_CACHE_SZ - 1)
160 off_t f_seekp
; /* seek pointer */
161 struct mfs_sblock
*f_fs
; /* pointer to super-block */
162 struct mfs_dinode f_di
; /* copy of on-disk inode */
163 uint f_nishift
; /* for blocks in indirect block */
164 block_t f_ind_cache_block
;
165 block_t f_ind_cache
[IND_CACHE_SZ
];
167 char *f_buf
; /* buffer for data block */
168 size_t f_buf_size
; /* size of data block */
169 daddr_t f_buf_blkno
; /* block number of data block */
172 static int read_inode(ino32_t
, struct open_file
*);
173 static int block_map(struct open_file
*, block_t
, block_t
*);
174 static int buf_read_file(struct open_file
*, void *, size_t *);
175 static int search_directory(const char *, int, struct open_file
*, ino32_t
*);
176 static int read_sblock(struct open_file
*, struct mfs_sblock
*);
179 * Read a new inode into a file structure.
182 read_inode(ino32_t inumber
, struct open_file
*f
)
184 struct file
*fp
= (struct file
*)f
->f_fsdata
;
185 struct mfs_sblock
*fs
= fp
->f_fs
;
189 daddr_t inode_sector
;
190 struct mfs_dinode
*dip
;
192 inode_sector
= FSBTODB(fs
, ino_to_fsba(fs
, inumber
));
195 * Read inode and save it.
199 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
200 inode_sector
, fs
->mfs_block_size
, buf
, &rsize
);
203 if (rsize
!= fs
->mfs_block_size
)
206 dip
= (struct mfs_dinode
*)(buf
+
207 INODE_SIZE
* ino_to_fsbo(fs
, inumber
));
208 mfs_iload(dip
, &fp
->f_di
);
211 * Clear out the old buffers
213 fp
->f_ind_cache_block
= ~0;
214 fp
->f_buf_blkno
= -1;
219 * Given an offset in a file, find the disk block number (not zone!)
220 * that contains that block.
223 block_map(struct open_file
*f
, block_t file_block
, block_t
*disk_block_p
)
225 struct file
*fp
= (struct file
*)f
->f_fsdata
;
226 struct mfs_sblock
*fs
= fp
->f_fs
;
229 block_t ind_block_num
;
234 int scale
= fs
->mfs_log_zone_size
; /* for block-zone conversion */
235 block_t
*buf
= (void *)fp
->f_buf
;
238 * Index structure of an inode:
240 * mdi_blocks[0..NR_DZONES-1]
241 * hold zone numbers for zones
244 * mdi_blocks[NR_DZONES+0]
245 * block NDADDR+0 is the single indirect block
246 * holds zone numbers for zones
247 * NR_DZONES .. NR_DZONES + MFS_NINDIR(fs)-1
249 * mdi_blocks[NR_DZONES+1]
250 * block NDADDR+1 is the double indirect block
251 * holds zone numbers for INDEX blocks for zones
252 * NR_DZONES + MFS_NINDIR(fs) ..
253 * NR_TZONES + MFS_NINDIR(fs) + MFS_NINDIR(fs)**2 - 1
256 zone
= file_block
>> scale
;
257 boff
= (int) (file_block
- (zone
<< scale
) ); /* relative blk in zone */
259 if (zone
< NR_DZONES
) {
261 zone_t z
= fs2h32(fp
->f_di
.mdi_zone
[zone
]);
263 *disk_block_p
= NO_BLOCK
;
266 *disk_block_p
= (block_t
) ((z
<< scale
) + boff
);
272 ind_cache
= zone
>> LN2_IND_CACHE_SZ
;
273 if (ind_cache
== fp
->f_ind_cache_block
) {
275 fs2h32(fp
->f_ind_cache
[zone
& IND_CACHE_MASK
]);
280 level
+= fp
->f_nishift
;
282 if (zone
< (block_t
)1 << level
)
284 if (level
> NIADDR
* fp
->f_nishift
)
285 /* Zone number too high */
287 zone
-= (block_t
)1 << level
;
291 fs2h32(fp
->f_di
.mdi_zone
[NR_DZONES
+ (level
/ fp
->f_nishift
- 1)]);
294 level
-= fp
->f_nishift
;
295 if (ind_block_num
== 0) {
296 *disk_block_p
= NO_BLOCK
; /* missing */
302 * If we were feeling brave, we could work out the number
303 * of the disk sector and read a single disk sector instead
304 * of a filesystem block.
305 * However we don't do this very often anyway...
307 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
308 FSBTODB(fs
, ind_block_num
), fs
->mfs_block_size
,
312 if (rsize
!= fs
->mfs_block_size
)
315 ind_block_num
= fs2h32(buf
[zone
>> level
]);
318 zone
&= (1 << level
) - 1;
321 /* Save the part of the block that contains this sector */
322 memcpy(fp
->f_ind_cache
, &buf
[zone
& ~IND_CACHE_MASK
],
323 IND_CACHE_SZ
* sizeof fp
->f_ind_cache
[0]);
324 fp
->f_ind_cache_block
= ind_cache
;
326 zone
= (zone_t
)ind_block_num
;
327 *disk_block_p
= (block_t
)((zone
<< scale
) + boff
);
332 * Read a portion of a file into an internal buffer.
333 * Return the location in the buffer and the amount in the buffer.
336 buf_read_file(struct open_file
*f
, void *v
, size_t *size_p
)
339 struct file
*fp
= (struct file
*)f
->f_fsdata
;
340 struct mfs_sblock
*fs
= fp
->f_fs
;
343 block_t disk_block
= 0; /* XXX: gcc */
347 off
= mfs_blkoff(fs
, fp
->f_seekp
);
348 file_block
= mfs_lblkno(fs
, fp
->f_seekp
);
349 block_size
= fs
->mfs_block_size
;
351 if (file_block
!= fp
->f_buf_blkno
) {
352 rc
= block_map(f
, file_block
, &disk_block
);
356 if (disk_block
== 0) {
357 memset(fp
->f_buf
, 0, block_size
);
358 fp
->f_buf_size
= block_size
;
361 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
362 FSBTODB(fs
, disk_block
),
363 block_size
, fp
->f_buf
, &fp
->f_buf_size
);
368 fp
->f_buf_blkno
= file_block
;
372 * Return address of byte in buffer corresponding to
373 * offset, and size of remainder of buffer after that
376 *buf_p
= fp
->f_buf
+ off
;
377 *size_p
= block_size
- off
;
380 * But truncate buffer at end of file.
382 if (*size_p
> fp
->f_di
.mdi_size
- fp
->f_seekp
)
383 *size_p
= fp
->f_di
.mdi_size
- fp
->f_seekp
;
389 * Search a directory for a name and return its
393 search_directory(const char *name
, int length
, struct open_file
*f
,
396 struct file
*fp
= (struct file
*)f
->f_fsdata
;
397 struct mfs_sblock
*fs
= fp
->f_fs
;
398 struct mfs_direct
*dp
;
399 struct mfs_direct
*dbuf
;
406 while (fp
->f_seekp
< (off_t
)fp
->f_di
.mdi_size
) {
407 rc
= buf_read_file(f
, (void *)&dbuf
, &buf_size
);
413 /* XXX we assume, that buf_read_file reads an fs block and
414 * doesn't truncate buffer. Currently i_size in MFS doesn't
415 * the same as size of allocated blocks, it makes buf_read_file
416 * to truncate buf_size.
418 if (buf_size
< fs
->mfs_block_size
)
419 buf_size
= fs
->mfs_block_size
;
421 for (dp
= dbuf
; dp
< &dbuf
[NR_DIR_ENTRIES(fs
)]; dp
++) {
423 if (fs2h32(dp
->mfsd_ino
) == (ino32_t
) 0)
425 /* Compute the length of the name */
426 cp
= memchr(dp
->mfsd_name
, '\0', sizeof(dp
->mfsd_name
));
428 namlen
= sizeof(dp
->mfsd_name
);
430 namlen
= cp
- (dp
->mfsd_name
);
432 if (namlen
== length
&&
433 !memcmp(name
, dp
->mfsd_name
, length
)) {
435 *inumber_p
= fs2h32(dp
->mfsd_ino
);
439 fp
->f_seekp
+= buf_size
;
445 read_sblock(struct open_file
*f
, struct mfs_sblock
*fs
)
447 static uint8_t sbbuf
[MINBSIZE
];
451 /* We must read amount multiple of sector size, hence we can't
452 * read SBSIZE and read MINBSIZE.
454 if (SBSIZE
> MINBSIZE
)
457 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
458 SUPER_BLOCK_OFF
/ DEV_BSIZE
, MINBSIZE
, sbbuf
, &buf_size
);
462 if (buf_size
!= MINBSIZE
)
465 mfs_sbload((void *)sbbuf
, fs
);
467 if (fs
->mfs_magic
!= SUPER_MAGIC
)
469 if (fs
->mfs_block_size
< MINBSIZE
)
471 if ((fs
->mfs_block_size
% 512) != 0)
473 if (SBSIZE
> fs
->mfs_block_size
)
475 if ((fs
->mfs_block_size
% INODE_SIZE
) != 0)
478 /* For even larger disks, a similar problem occurs with s_firstdatazone.
479 * If the on-disk field contains zero, we assume that the value was too
480 * large to fit, and compute it on the fly.
482 if (fs
->mfs_firstdatazone_old
== 0) {
484 offset
= START_BLOCK
+ fs
->mfs_imap_blocks
+ fs
->mfs_zmap_blocks
;
485 offset
+= (fs
->mfs_ninodes
+ fs
->mfs_inodes_per_block
- 1) /
486 fs
->mfs_inodes_per_block
;
488 fs
->mfs_firstdatazone
=
489 (offset
+ (1 << fs
->mfs_log_zone_size
) - 1) >>
490 fs
->mfs_log_zone_size
;
492 fs
->mfs_firstdatazone
= (zone_t
) fs
->mfs_firstdatazone_old
;
495 if (fs
->mfs_imap_blocks
< 1 || fs
->mfs_zmap_blocks
< 1
496 || fs
->mfs_ninodes
< 1 || fs
->mfs_zones
< 1
497 || fs
->mfs_firstdatazone
<= 4
498 || fs
->mfs_firstdatazone
>= fs
->mfs_zones
499 || (unsigned) fs
->mfs_log_zone_size
> 4)
502 /* compute in-memory mfs_sblock values */
503 fs
->mfs_inodes_per_block
= fs
->mfs_block_size
/ INODE_SIZE
;
507 int32_t mult
= fs
->mfs_block_size
>> LOG_MINBSIZE
;
508 int ln2
= LOG_MINBSIZE
;
510 for (; mult
!= 1; ln2
++)
513 fs
->mfs_bshift
= ln2
;
514 /* XXX assume hw bsize = 512 */
515 fs
->mfs_fsbtodb
= ln2
- LOG_MINBSIZE
+ 1;
518 fs
->mfs_qbmask
= fs
->mfs_block_size
- 1;
519 fs
->mfs_bmask
= ~fs
->mfs_qbmask
;
528 minixfs3_open(const char *path
, struct open_file
*f
)
530 #ifndef LIBSA_FS_SINGLECOMPONENT
531 const char *cp
, *ncp
;
536 struct mfs_sblock
*fs
;
538 #ifndef LIBSA_NO_FS_SYMLINK
539 ino32_t parent_inumber
;
541 char namebuf
[MAXPATHLEN
+1];
545 /* allocate file system specific data structure */
546 fp
= alloc(sizeof(struct file
));
547 memset(fp
, 0, sizeof(struct file
));
548 f
->f_fsdata
= (void *)fp
;
550 /* allocate space and read super block */
551 fs
= alloc(sizeof(*fs
));
552 memset(fs
, 0, sizeof(*fs
));
556 rc
= read_sblock(f
, fs
);
560 /* alloc a block sized buffer used for all fs transfers */
561 fp
->f_buf
= alloc(fs
->mfs_block_size
);
564 * Calculate indirect block levels.
571 * We note that the number of indirect blocks is always
572 * a power of 2. This lets us use shifts and masks instead
573 * of divide and remainder and avoinds pulling in the
574 * 64bit division routine into the boot code.
576 mult
= MFS_NINDIR(fs
);
578 if (!powerof2(mult
)) {
579 /* Hummm was't a power of 2 */
584 for (ln2
= 0; mult
!= 1; ln2
++)
590 inumber
= ROOT_INODE
;
591 if ((rc
= read_inode(inumber
, f
)) != 0)
594 #ifndef LIBSA_FS_SINGLECOMPONENT
599 * Remove extra separators
607 * Check that current node is a directory.
609 if ((fp
->f_di
.mdi_mode
& I_TYPE
) != I_DIRECTORY
) {
615 * Get next component of path name.
618 while ((c
= *cp
) != '\0' && c
!= '/')
622 * Look up component in current directory.
623 * Save directory inumber in case we find a
626 #ifndef LIBSA_NO_FS_SYMLINK
627 parent_inumber
= inumber
;
629 rc
= search_directory(ncp
, cp
- ncp
, f
, &inumber
);
634 * Open next component.
636 if ((rc
= read_inode(inumber
, f
)) != 0)
639 #ifndef LIBSA_NO_FS_SYMLINK
641 * Check for symbolic link.
643 if ((fp
->f_di
.mdi_mode
& I_TYPE
) == I_SYMBOLIC_LINK
) {
644 int link_len
= fp
->f_di
.mdi_size
;
651 if (link_len
+ len
> MAXPATHLEN
||
652 ++nlinks
> MAXSYMLINKS
) {
657 memmove(&namebuf
[link_len
], cp
, len
+ 1);
660 * Read file for symbolic link
663 rc
= block_map(f
, (block_t
)0, &disk_block
);
668 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
,
669 F_READ
, FSBTODB(fs
, disk_block
),
670 fs
->mfs_block_size
, buf
, &buf_size
);
674 memcpy(namebuf
, buf
, link_len
);
677 * If relative pathname, restart at parent directory.
678 * If absolute pathname, restart at root.
682 inumber
= parent_inumber
;
684 inumber
= (ino32_t
) ROOT_INODE
;
686 if ((rc
= read_inode(inumber
, f
)) != 0)
689 #endif /* !LIBSA_NO_FS_SYMLINK */
693 * Found terminal component.
697 #else /* !LIBSA_FS_SINGLECOMPONENT */
699 /* look up component in the current (root) directory */
700 rc
= search_directory(path
, strlen(path
), f
, &inumber
);
705 rc
= read_inode(inumber
, f
);
707 #endif /* !LIBSA_FS_SINGLECOMPONENT */
709 fp
->f_seekp
= 0; /* reset seek pointer */
719 minixfs3_close(struct open_file
*f
)
721 struct file
*fp
= (struct file
*)f
->f_fsdata
;
728 dealloc(fp
->f_buf
, fp
->f_fs
->mfs_block_size
);
729 dealloc(fp
->f_fs
, sizeof(*fp
->f_fs
));
730 dealloc(fp
, sizeof(struct file
));
735 * Copy a portion of a file into kernel memory.
736 * Cross block boundaries when necessary.
739 minixfs3_read(struct open_file
*f
, void *start
, size_t size
, size_t *resid
)
741 struct file
*fp
= (struct file
*)f
->f_fsdata
;
749 if (fp
->f_seekp
>= (off_t
)fp
->f_di
.mdi_size
)
752 rc
= buf_read_file(f
, &buf
, &buf_size
);
757 if (csize
> buf_size
)
760 memcpy(addr
, buf
, csize
);
762 fp
->f_seekp
+= csize
;
775 #ifndef LIBSA_NO_FS_WRITE
777 minixfs3_write(struct open_file
*f
, void *start
, size_t size
, size_t *resid
)
782 #endif /* !LIBSA_NO_FS_WRITE */
784 #ifndef LIBSA_NO_FS_SEEK
786 minixfs3_seek(struct open_file
*f
, off_t offset
, int where
)
788 struct file
*fp
= (struct file
*)f
->f_fsdata
;
792 fp
->f_seekp
= offset
;
795 fp
->f_seekp
+= offset
;
798 fp
->f_seekp
= fp
->f_di
.mdi_size
- offset
;
805 #endif /* !LIBSA_NO_FS_SEEK */
808 minixfs3_stat(struct open_file
*f
, struct stat
*sb
)
810 struct file
*fp
= (struct file
*)f
->f_fsdata
;
812 /* only important stuff */
813 memset(sb
, 0, sizeof *sb
);
814 sb
->st_mode
= fp
->f_di
.mdi_mode
;
815 sb
->st_uid
= fp
->f_di
.mdi_uid
;
816 sb
->st_gid
= fp
->f_di
.mdi_gid
;
817 sb
->st_size
= fp
->f_di
.mdi_size
;
821 #if defined(LIBSA_ENABLE_LS_OP)
823 #if defined(__minix) && !defined(LIBSA_ENABLE_LOAD_MODS_OP)
825 minixfs3_ls(struct open_file
*f
, const char *pattern
)
827 __compactcall lsentry_t
*
828 minixfs3_list(struct open_file
*f
, const char *pattern
);
831 minixfs3_ls(struct open_file
*f
, const char *pattern
)
833 lsentry_t
*names
= minixfs3_list(f
, pattern
);
839 minixfs3_load_mods(struct open_file
*f
, const char *pattern
,
840 void (*funcp
)(char *), char *path
)
842 lsentry_t
*names
= minixfs3_list(f
, pattern
);
843 lsapply(names
, pattern
, funcp
, path
);
847 __compactcall lsentry_t
*
848 minixfs3_list(struct open_file
*f
, const char *pattern
)
849 #endif /* defined(__minix) && defined(LIBSA_ENABLE_LOAD_MODS_OP) */
851 struct file
*fp
= (struct file
*)f
->f_fsdata
;
852 struct mfs_sblock
*fs
= fp
->f_fs
;
853 struct mfs_direct
*dp
;
854 struct mfs_direct
*dbuf
;
856 lsentry_t
*names
= 0;
859 while (fp
->f_seekp
< (off_t
)fp
->f_di
.mdi_size
) {
860 int rc
= buf_read_file(f
, &dbuf
, &buf_size
);
864 /* XXX we assume, that buf_read_file reads an fs block and
865 * doesn't truncate buffer. Currently i_size in MFS doesn't
866 * the same as size of allocated blocks, it makes buf_read_file
867 * to truncate buf_size.
869 if (buf_size
< fs
->mfs_block_size
)
870 buf_size
= fs
->mfs_block_size
;
872 for (dp
= dbuf
; dp
< &dbuf
[NR_DIR_ENTRIES(fs
)]; dp
++) {
876 if (fs2h32(dp
->mfsd_ino
) == 0)
879 /* Compute the length of the name,
880 * We don't use strlen and strcpy, because original MFS
883 cp
= memchr(dp
->mfsd_name
, '\0', sizeof(dp
->mfsd_name
));
885 namlen
= sizeof(dp
->mfsd_name
);
887 namlen
= cp
- (dp
->mfsd_name
);
889 lsadd(&names
, pattern
, dp
->mfsd_name
, namlen
,
890 fs2h32(dp
->mfsd_ino
), "?");
892 fp
->f_seekp
+= buf_size
;
895 #if defined(__minix) && defined(LIBSA_ENABLE_LOAD_MODS_OP)
900 #endif /* defined(__minix) && defined(LIBSA_ENABLE_LOAD_MODS_OP) */
905 * byte swap functions for big endian machines
906 * (mfs is always little endian)
909 /* These functions are only needed if native byte order is not big endian */
910 #if BYTE_ORDER == BIG_ENDIAN
912 minixfs3_sb_bswap(struct mfs_sblock
*old
, struct mfs_sblock
*new)
914 new->mfs_ninodes
= bswap32(old
->mfs_ninodes
);
915 new->mfs_nzones
= bswap16(old
->mfs_nzones
);
916 new->mfs_imap_blocks
= bswap16(old
->mfs_imap_blocks
);
917 new->mfs_zmap_blocks
= bswap16(old
->mfs_zmap_blocks
);
918 new->mfs_firstdatazone_old
= bswap16(old
->mfs_firstdatazone_old
);
919 new->mfs_log_zone_size
= bswap16(old
->mfs_log_zone_size
);
920 new->mfs_max_size
= bswap32(old
->mfs_max_size
);
921 new->mfs_zones
= bswap32(old
->mfs_zones
);
922 new->mfs_magic
= bswap16(old
->mfs_magic
);
923 new->mfs_block_size
= bswap16(old
->mfs_block_size
);
924 new->mfs_disk_version
= old
->mfs_disk_version
;
927 void minixfs3_i_bswap(struct mfs_dinode
*old
, struct mfs_dinode
*new)
931 new->mdi_mode
= bswap16(old
->mdi_mode
);
932 new->mdi_nlinks
= bswap16(old
->mdi_nlinks
);
933 new->mdi_uid
= bswap16(old
->mdi_uid
);
934 new->mdi_gid
= bswap16(old
->mdi_gid
);
935 new->mdi_size
= bswap32(old
->mdi_size
);
936 new->mdi_atime
= bswap32(old
->mdi_atime
);
937 new->mdi_mtime
= bswap32(old
->mdi_mtime
);
938 new->mdi_ctime
= bswap32(old
->mdi_ctime
);
940 /* We don't swap here, because indirects must be swapped later
941 * anyway, hence everything is done by block_map().
943 for (i
= 0; i
< NR_TZONES
; i
++)
944 new->mdi_zone
[i
] = old
->mdi_zone
[i
];