1 /* $NetBSD: ext2fs.c,v 1.20 2014/03/20 03:13:18 christos Exp $ */
4 * Copyright (c) 1997 Manuel Bouyer.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The Regents of the University of California. All rights reserved.
31 * This code is derived from software contributed to Berkeley by
32 * The Mach Operating System project at Carnegie-Mellon University.
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
37 * 1. Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in the
41 * documentation and/or other materials provided with the distribution.
42 * 3. Neither the name of the University nor the names of its contributors
43 * may be used to endorse or promote products derived from this software
44 * without specific prior written permission.
46 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * Copyright (c) 1990, 1991 Carnegie Mellon University
60 * All Rights Reserved.
64 * Permission to use, copy, modify and distribute this software and its
65 * documentation is hereby granted, provided that both the copyright
66 * notice and this permission notice appear in all copies of the
67 * software, derivative works or modified versions, and any portions
68 * thereof, and that both notices appear in supporting documentation.
70 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
71 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
72 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
74 * Carnegie Mellon requests users of this software to return to
76 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
77 * School of Computer Science
78 * Carnegie Mellon University
79 * Pittsburgh PA 15213-3890
81 * any improvements or extensions that they make and grant Carnegie the
82 * rights to redistribute these changes.
86 * Stand-alone file reading package for Ext2 file system.
89 /* #define EXT2FS_DEBUG */
91 #include <sys/param.h>
93 #include <ufs/ext2fs/ext2fs_dinode.h>
94 #include <ufs/ext2fs/ext2fs_dir.h>
95 #include <ufs/ext2fs/ext2fs.h>
97 #include <lib/libkern/libkern.h>
105 #if defined(LIBSA_FS_SINGLECOMPONENT) && !defined(LIBSA_NO_FS_SYMLINK)
106 #define LIBSA_NO_FS_SYMLINK
109 #if defined(LIBSA_NO_TWIDDLE)
114 #define indp_t int32_t
116 typedef uint32_t ino32_t
;
118 #define FSBTODB(fs, indp) EXT2_FSBTODB(fs, indp)
122 * To avoid having a lot of filesystem-block sized buffers lurking (which
123 * could be 32k) we only keep a few entries of the indirect block map.
124 * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
125 * ~13 times pulling in a 6M kernel.
126 * The cache size must be smaller than the smallest filesystem block,
127 * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
129 #define LN2_IND_CACHE_SZ 6
130 #define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ)
131 #define IND_CACHE_MASK (IND_CACHE_SZ - 1)
137 off_t f_seekp
; /* seek pointer */
138 struct m_ext2fs
*f_fs
; /* pointer to super-block */
139 struct ext2fs_dinode f_di
; /* copy of on-disk inode */
140 uint f_nishift
; /* for blocks in indirect block */
141 indp_t f_ind_cache_block
;
142 indp_t f_ind_cache
[IND_CACHE_SZ
];
144 char *f_buf
; /* buffer for data block */
145 size_t f_buf_size
; /* size of data block */
146 daddr_t f_buf_blkno
; /* block number of data block */
150 static int read_inode(ino32_t
, struct open_file
*);
151 static int block_map(struct open_file
*, indp_t
, indp_t
*);
152 static int buf_read_file(struct open_file
*, char **, size_t *);
153 static int search_directory(const char *, int, struct open_file
*, ino32_t
*);
154 static int read_sblock(struct open_file
*, struct m_ext2fs
*);
155 static int read_gdblock(struct open_file
*, struct m_ext2fs
*);
157 static void dump_sblock(struct m_ext2fs
*);
161 * Read a new inode into a file structure.
164 read_inode(ino32_t inumber
, struct open_file
*f
)
166 struct file
*fp
= (struct file
*)f
->f_fsdata
;
167 struct m_ext2fs
*fs
= fp
->f_fs
;
171 daddr_t inode_sector
;
172 struct ext2fs_dinode
*dip
;
174 inode_sector
= FSBTODB(fs
, ino_to_fsba(fs
, inumber
));
177 * Read inode and save it.
181 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
182 inode_sector
, fs
->e2fs_bsize
, buf
, &rsize
);
185 if (rsize
!= fs
->e2fs_bsize
)
188 dip
= (struct ext2fs_dinode
*)(buf
+
189 EXT2_DINODE_SIZE(fs
) * ino_to_fsbo(fs
, inumber
));
190 e2fs_iload(dip
, &fp
->f_di
);
193 * Clear out the old buffers
195 fp
->f_ind_cache_block
= ~0;
196 fp
->f_buf_blkno
= -1;
201 * Given an offset in a file, find the disk block number that
202 * contains that block.
205 block_map(struct open_file
*f
, indp_t file_block
, indp_t
*disk_block_p
)
207 struct file
*fp
= (struct file
*)f
->f_fsdata
;
208 struct m_ext2fs
*fs
= fp
->f_fs
;
211 indp_t ind_block_num
;
214 indp_t
*buf
= (void *)fp
->f_buf
;
217 * Index structure of an inode:
219 * e2di_blocks[0..EXT2FS_NDADDR-1]
220 * hold block numbers for blocks
223 * e2di_blocks[EXT2FS_NDADDR+0]
224 * block EXT2FS_NDADDR+0 is the single indirect block
225 * holds block numbers for blocks
226 * EXT2FS_NDADDR .. EXT2FS_NDADDR + EXT2_NINDIR(fs)-1
228 * e2di_blocks[EXT2FS_NDADDR+1]
229 * block EXT2FS_NDADDR+1 is the double indirect block
230 * holds block numbers for INDEX blocks for blocks
231 * EXT2FS_NDADDR + EXT2_NINDIR(fs) ..
232 * EXT2FS_NDADDR + EXT2_NINDIR(fs) + EXT2_NINDIR(fs)**2 - 1
234 * e2di_blocks[EXT2FS_NDADDR+2]
235 * block EXT2FS_NDADDR+2 is the triple indirect block
236 * holds block numbers for double-indirect
238 * EXT2FS_NDADDR + EXT2_NINDIR(fs) + EXT2_NINDIR(fs)**2 ..
239 * EXT2FS_NDADDR + EXT2_NINDIR(fs) + EXT2_NINDIR(fs)**2
240 * + EXT2_NINDIR(fs)**3 - 1
243 if (file_block
< EXT2FS_NDADDR
) {
245 *disk_block_p
= fs2h32(fp
->f_di
.e2di_blocks
[file_block
]);
249 file_block
-= EXT2FS_NDADDR
;
251 ind_cache
= file_block
>> LN2_IND_CACHE_SZ
;
252 if (ind_cache
== fp
->f_ind_cache_block
) {
254 fs2h32(fp
->f_ind_cache
[file_block
& IND_CACHE_MASK
]);
259 level
+= fp
->f_nishift
;
260 if (file_block
< (indp_t
)1 << level
)
262 if (level
> EXT2FS_NIADDR
* fp
->f_nishift
)
263 /* Block number too high */
265 file_block
-= (indp_t
)1 << level
;
269 fs2h32(fp
->f_di
.e2di_blocks
[EXT2FS_NDADDR
+
270 (level
/ fp
->f_nishift
- 1)]);
273 level
-= fp
->f_nishift
;
274 if (ind_block_num
== 0) {
275 *disk_block_p
= 0; /* missing */
281 * If we were feeling brave, we could work out the number
282 * of the disk sector and read a single disk sector instead
283 * of a filesystem block.
284 * However we don't do this very often anyway...
286 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
287 FSBTODB(fp
->f_fs
, ind_block_num
), fs
->e2fs_bsize
,
291 if (rsize
!= fs
->e2fs_bsize
)
293 ind_block_num
= fs2h32(buf
[file_block
>> level
]);
296 file_block
&= (1 << level
) - 1;
299 /* Save the part of the block that contains this sector */
300 memcpy(fp
->f_ind_cache
, &buf
[file_block
& ~IND_CACHE_MASK
],
301 IND_CACHE_SZ
* sizeof fp
->f_ind_cache
[0]);
302 fp
->f_ind_cache_block
= ind_cache
;
304 *disk_block_p
= ind_block_num
;
310 * Read a portion of a file into an internal buffer.
311 * Return the location in the buffer and the amount in the buffer.
314 buf_read_file(struct open_file
*f
, char **buf_p
, size_t *size_p
)
316 struct file
*fp
= (struct file
*)f
->f_fsdata
;
317 struct m_ext2fs
*fs
= fp
->f_fs
;
320 indp_t disk_block
= 0; /* XXX: gcc */
324 off
= ext2_blkoff(fs
, fp
->f_seekp
);
325 file_block
= ext2_lblkno(fs
, fp
->f_seekp
);
326 block_size
= fs
->e2fs_bsize
; /* no fragment */
328 if (file_block
!= fp
->f_buf_blkno
) {
329 rc
= block_map(f
, file_block
, &disk_block
);
333 if (disk_block
== 0) {
334 memset(fp
->f_buf
, 0, block_size
);
335 fp
->f_buf_size
= block_size
;
338 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
339 FSBTODB(fs
, disk_block
),
340 block_size
, fp
->f_buf
, &fp
->f_buf_size
);
345 fp
->f_buf_blkno
= file_block
;
349 * Return address of byte in buffer corresponding to
350 * offset, and size of remainder of buffer after that
353 *buf_p
= fp
->f_buf
+ off
;
354 *size_p
= block_size
- off
;
357 * But truncate buffer at end of file.
359 /* XXX should handle LARGEFILE */
360 if (*size_p
> fp
->f_di
.e2di_size
- fp
->f_seekp
)
361 *size_p
= fp
->f_di
.e2di_size
- fp
->f_seekp
;
367 * Search a directory for a name and return its
371 search_directory(const char *name
, int length
, struct open_file
*f
,
374 struct file
*fp
= (struct file
*)f
->f_fsdata
;
375 struct ext2fs_direct
*dp
;
376 struct ext2fs_direct
*edp
;
383 /* XXX should handle LARGEFILE */
384 while (fp
->f_seekp
< (off_t
)fp
->f_di
.e2di_size
) {
385 rc
= buf_read_file(f
, &buf
, &buf_size
);
389 dp
= (struct ext2fs_direct
*)buf
;
390 edp
= (struct ext2fs_direct
*)(buf
+ buf_size
);
392 dp
= (void *)((char *)dp
+ fs2h16(dp
->e2d_reclen
))) {
393 if (fs2h16(dp
->e2d_reclen
) <= 0)
395 if (fs2h32(dp
->e2d_ino
) == (ino32_t
)0)
397 namlen
= dp
->e2d_namlen
;
398 if (namlen
== length
&&
399 !memcmp(name
, dp
->e2d_name
, length
)) {
401 *inumber_p
= fs2h32(dp
->e2d_ino
);
405 fp
->f_seekp
+= buf_size
;
411 read_sblock(struct open_file
*f
, struct m_ext2fs
*fs
)
413 static uint8_t sbbuf
[SBSIZE
];
414 struct ext2fs ext2fs
;
418 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
419 SBOFF
/ DEV_BSIZE
, SBSIZE
, sbbuf
, &buf_size
);
423 if (buf_size
!= SBSIZE
)
426 e2fs_sbload((void *)sbbuf
, &ext2fs
);
427 if (ext2fs
.e2fs_magic
!= E2FS_MAGIC
)
429 if (ext2fs
.e2fs_rev
> E2FS_REV1
||
430 (ext2fs
.e2fs_rev
== E2FS_REV1
&&
431 (ext2fs
.e2fs_first_ino
!= EXT2_FIRSTINO
||
432 (ext2fs
.e2fs_inode_size
!= 128 && ext2fs
.e2fs_inode_size
!= 256) ||
433 ext2fs
.e2fs_features_incompat
& ~EXT2F_INCOMPAT_SUPP
))) {
437 e2fs_sbload((void *)sbbuf
, &fs
->e2fs
);
438 /* compute in-memory m_ext2fs values */
440 howmany(fs
->e2fs
.e2fs_bcount
- fs
->e2fs
.e2fs_first_dblock
,
442 /* XXX assume hw bsize = 512 */
443 fs
->e2fs_fsbtodb
= fs
->e2fs
.e2fs_log_bsize
+ 1;
444 fs
->e2fs_bsize
= MINBSIZE
<< fs
->e2fs
.e2fs_log_bsize
;
445 fs
->e2fs_bshift
= LOG_MINBSIZE
+ fs
->e2fs
.e2fs_log_bsize
;
446 fs
->e2fs_qbmask
= fs
->e2fs_bsize
- 1;
447 fs
->e2fs_bmask
= ~fs
->e2fs_qbmask
;
449 howmany(fs
->e2fs_ncg
, fs
->e2fs_bsize
/ sizeof(struct ext2_gd
));
450 fs
->e2fs_ipb
= fs
->e2fs_bsize
/ ext2fs
.e2fs_inode_size
;
451 fs
->e2fs_itpg
= fs
->e2fs
.e2fs_ipg
/ fs
->e2fs_ipb
;
457 read_gdblock(struct open_file
*f
, struct m_ext2fs
*fs
)
459 struct file
*fp
= (struct file
*)f
->f_fsdata
;
464 gdpb
= fs
->e2fs_bsize
/ sizeof(struct ext2_gd
);
466 for (i
= 0; i
< fs
->e2fs_ngdb
; i
++) {
467 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
468 FSBTODB(fs
, fs
->e2fs
.e2fs_first_dblock
+
469 1 /* superblock */ + i
),
470 fs
->e2fs_bsize
, fp
->f_buf
, &rsize
);
473 if (rsize
!= fs
->e2fs_bsize
)
476 e2fs_cgload((struct ext2_gd
*)fp
->f_buf
,
477 &fs
->e2fs_gd
[i
* gdpb
],
478 (i
== (fs
->e2fs_ngdb
- 1)) ?
479 (fs
->e2fs_ncg
- gdpb
* i
) * sizeof(struct ext2_gd
):
491 ext2fs_open(const char *path
, struct open_file
*f
)
493 #ifndef LIBSA_FS_SINGLECOMPONENT
494 const char *cp
, *ncp
;
501 #ifndef LIBSA_NO_FS_SYMLINK
502 ino32_t parent_inumber
;
504 char namebuf
[MAXPATHLEN
+1];
508 /* allocate file system specific data structure */
509 fp
= alloc(sizeof(struct file
));
510 memset(fp
, 0, sizeof(struct file
));
511 f
->f_fsdata
= (void *)fp
;
513 /* allocate space and read super block */
514 fs
= alloc(sizeof(*fs
));
515 memset(fs
, 0, sizeof(*fs
));
519 rc
= read_sblock(f
, fs
);
527 /* alloc a block sized buffer used for all fs transfers */
528 fp
->f_buf
= alloc(fs
->e2fs_bsize
);
530 /* read group descriptor blocks */
531 fs
->e2fs_gd
= alloc(sizeof(struct ext2_gd
) * fs
->e2fs_ncg
);
532 rc
= read_gdblock(f
, fs
);
537 * Calculate indirect block levels.
544 * We note that the number of indirect blocks is always
545 * a power of 2. This lets us use shifts and masks instead
546 * of divide and remainder and avoinds pulling in the
547 * 64bit division routine into the boot code.
549 mult
= EXT2_NINDIR(fs
);
551 if (!powerof2(mult
)) {
552 /* Hummm was't a power of 2 */
557 for (ln2
= 0; mult
!= 1; ln2
++)
563 inumber
= EXT2_ROOTINO
;
564 if ((rc
= read_inode(inumber
, f
)) != 0)
567 #ifndef LIBSA_FS_SINGLECOMPONENT
572 * Remove extra separators
580 * Check that current node is a directory.
582 if ((fp
->f_di
.e2di_mode
& EXT2_IFMT
) != EXT2_IFDIR
) {
588 * Get next component of path name.
591 while ((c
= *cp
) != '\0' && c
!= '/')
595 * Look up component in current directory.
596 * Save directory inumber in case we find a
599 #ifndef LIBSA_NO_FS_SYMLINK
600 parent_inumber
= inumber
;
602 rc
= search_directory(ncp
, cp
- ncp
, f
, &inumber
);
607 * Open next component.
609 if ((rc
= read_inode(inumber
, f
)) != 0)
612 #ifndef LIBSA_NO_FS_SYMLINK
614 * Check for symbolic link.
616 if ((fp
->f_di
.e2di_mode
& EXT2_IFMT
) == EXT2_IFLNK
) {
617 /* XXX should handle LARGEFILE */
618 int link_len
= fp
->f_di
.e2di_size
;
623 if (link_len
+ len
> MAXPATHLEN
||
624 ++nlinks
> MAXSYMLINKS
) {
629 memmove(&namebuf
[link_len
], cp
, len
+ 1);
631 if (link_len
< EXT2_MAXSYMLINKLEN
) {
632 memcpy(namebuf
, fp
->f_di
.e2di_blocks
, link_len
);
635 * Read file for symbolic link
641 rc
= block_map(f
, (indp_t
)0, &disk_block
);
646 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
,
647 F_READ
, FSBTODB(fs
, disk_block
),
648 fs
->e2fs_bsize
, buf
, &buf_size
);
652 memcpy(namebuf
, buf
, link_len
);
656 * If relative pathname, restart at parent directory.
657 * If absolute pathname, restart at root.
661 inumber
= parent_inumber
;
663 inumber
= (ino32_t
)EXT2_ROOTINO
;
665 if ((rc
= read_inode(inumber
, f
)) != 0)
668 #endif /* !LIBSA_NO_FS_SYMLINK */
672 * Found terminal component.
676 #else /* !LIBSA_FS_SINGLECOMPONENT */
678 /* look up component in the current (root) directory */
679 rc
= search_directory(path
, strlen(path
), f
, &inumber
);
684 rc
= read_inode(inumber
, f
);
686 #endif /* !LIBSA_FS_SINGLECOMPONENT */
688 fp
->f_seekp
= 0; /* reset seek pointer */
699 ext2fs_close(struct open_file
*f
)
701 struct file
*fp
= (struct file
*)f
->f_fsdata
;
707 if (fp
->f_fs
->e2fs_gd
)
708 dealloc(fp
->f_fs
->e2fs_gd
,
709 sizeof(struct ext2_gd
) * fp
->f_fs
->e2fs_ncg
);
711 dealloc(fp
->f_buf
, fp
->f_fs
->e2fs_bsize
);
712 dealloc(fp
->f_fs
, sizeof(*fp
->f_fs
));
713 dealloc(fp
, sizeof(struct file
));
718 * Copy a portion of a file into kernel memory.
719 * Cross block boundaries when necessary.
722 ext2fs_read(struct open_file
*f
, void *start
, size_t size
, size_t *resid
)
724 struct file
*fp
= (struct file
*)f
->f_fsdata
;
732 /* XXX should handle LARGEFILE */
733 if (fp
->f_seekp
>= (off_t
)fp
->f_di
.e2di_size
)
736 rc
= buf_read_file(f
, &buf
, &buf_size
);
741 if (csize
> buf_size
)
744 memcpy(addr
, buf
, csize
);
746 fp
->f_seekp
+= csize
;
758 #ifndef LIBSA_NO_FS_WRITE
760 ext2fs_write(struct open_file
*f
, void *start
, size_t size
, size_t *resid
)
765 #endif /* !LIBSA_NO_FS_WRITE */
767 #ifndef LIBSA_NO_FS_SEEK
769 ext2fs_seek(struct open_file
*f
, off_t offset
, int where
)
771 struct file
*fp
= (struct file
*)f
->f_fsdata
;
775 fp
->f_seekp
= offset
;
778 fp
->f_seekp
+= offset
;
781 /* XXX should handle LARGEFILE */
782 fp
->f_seekp
= fp
->f_di
.e2di_size
- offset
;
789 #endif /* !LIBSA_NO_FS_SEEK */
792 ext2fs_stat(struct open_file
*f
, struct stat
*sb
)
794 struct file
*fp
= (struct file
*)f
->f_fsdata
;
796 /* only important stuff */
797 memset(sb
, 0, sizeof *sb
);
798 sb
->st_mode
= fp
->f_di
.e2di_mode
;
799 sb
->st_uid
= fp
->f_di
.e2di_uid
;
800 sb
->st_gid
= fp
->f_di
.e2di_gid
;
801 /* XXX should handle LARGEFILE */
802 sb
->st_size
= fp
->f_di
.e2di_size
;
806 #if defined(LIBSA_ENABLE_LS_OP)
810 static const char *const typestr
[] = {
822 ext2fs_ls(struct open_file
*f
, const char *pattern
)
824 struct file
*fp
= (struct file
*)f
->f_fsdata
;
825 size_t block_size
= fp
->f_fs
->e2fs_bsize
;
828 lsentry_t
*names
= NULL
;
831 while (fp
->f_seekp
< (off_t
)fp
->f_di
.e2di_size
) {
832 struct ext2fs_direct
*dp
, *edp
;
833 int rc
= buf_read_file(f
, &buf
, &buf_size
);
836 if (buf_size
!= block_size
|| buf_size
== 0)
839 dp
= (struct ext2fs_direct
*)buf
;
840 edp
= (struct ext2fs_direct
*)(buf
+ buf_size
);
843 dp
= (void *)((char *)dp
+ fs2h16(dp
->e2d_reclen
))) {
846 if (fs2h16(dp
->e2d_reclen
) <= 0)
849 if (fs2h32(dp
->e2d_ino
) == 0)
852 if (dp
->e2d_type
>= NELEM(typestr
) ||
853 !(t
= typestr
[dp
->e2d_type
])) {
855 * This does not handle "old"
856 * filesystems properly. On little
857 * endian machines, we get a bogus
858 * type name if the namlen matches a
859 * valid type identifier. We could
860 * check if we read namlen "0" and
861 * handle this case specially, if
862 * there were a pressing need...
864 printf("bad dir entry\n");
867 lsadd(&names
, pattern
, dp
->e2d_name
,
868 strlen(dp
->e2d_name
), fs2h32(dp
->e2d_ino
), t
);
870 fp
->f_seekp
+= buf_size
;
877 #if defined(__minix) && defined(LIBSA_ENABLE_LOAD_MODS_OP)
879 ext2fs_load_mods(struct open_file
*f
, const char *pattern
,
880 void (*funcp
)(char *), char *path
)
882 load_modsunsup("extfs");
884 #endif /* defined(__minix) && defined(LIBSA_ENABLE_LOAD_MODS_OP) */
888 * byte swap functions for big endian machines
889 * (ext2fs is always little endian)
891 * XXX: We should use src/sys/ufs/ext2fs/ext2fs_bswap.c
894 /* These functions are only needed if native byte order is not big endian */
895 #if BYTE_ORDER == BIG_ENDIAN
897 e2fs_sb_bswap(struct ext2fs
*old
, struct ext2fs
*new)
900 /* preserve unused fields */
901 memcpy(new, old
, sizeof(struct ext2fs
));
902 new->e2fs_icount
= bswap32(old
->e2fs_icount
);
903 new->e2fs_bcount
= bswap32(old
->e2fs_bcount
);
904 new->e2fs_rbcount
= bswap32(old
->e2fs_rbcount
);
905 new->e2fs_fbcount
= bswap32(old
->e2fs_fbcount
);
906 new->e2fs_ficount
= bswap32(old
->e2fs_ficount
);
907 new->e2fs_first_dblock
= bswap32(old
->e2fs_first_dblock
);
908 new->e2fs_log_bsize
= bswap32(old
->e2fs_log_bsize
);
909 new->e2fs_fsize
= bswap32(old
->e2fs_fsize
);
910 new->e2fs_bpg
= bswap32(old
->e2fs_bpg
);
911 new->e2fs_fpg
= bswap32(old
->e2fs_fpg
);
912 new->e2fs_ipg
= bswap32(old
->e2fs_ipg
);
913 new->e2fs_mtime
= bswap32(old
->e2fs_mtime
);
914 new->e2fs_wtime
= bswap32(old
->e2fs_wtime
);
915 new->e2fs_mnt_count
= bswap16(old
->e2fs_mnt_count
);
916 new->e2fs_max_mnt_count
= bswap16(old
->e2fs_max_mnt_count
);
917 new->e2fs_magic
= bswap16(old
->e2fs_magic
);
918 new->e2fs_state
= bswap16(old
->e2fs_state
);
919 new->e2fs_beh
= bswap16(old
->e2fs_beh
);
920 new->e2fs_minrev
= bswap16(old
->e2fs_minrev
);
921 new->e2fs_lastfsck
= bswap32(old
->e2fs_lastfsck
);
922 new->e2fs_fsckintv
= bswap32(old
->e2fs_fsckintv
);
923 new->e2fs_creator
= bswap32(old
->e2fs_creator
);
924 new->e2fs_rev
= bswap32(old
->e2fs_rev
);
925 new->e2fs_ruid
= bswap16(old
->e2fs_ruid
);
926 new->e2fs_rgid
= bswap16(old
->e2fs_rgid
);
927 new->e2fs_first_ino
= bswap32(old
->e2fs_first_ino
);
928 new->e2fs_inode_size
= bswap16(old
->e2fs_inode_size
);
929 new->e2fs_block_group_nr
= bswap16(old
->e2fs_block_group_nr
);
930 new->e2fs_features_compat
= bswap32(old
->e2fs_features_compat
);
931 new->e2fs_features_incompat
= bswap32(old
->e2fs_features_incompat
);
932 new->e2fs_features_rocompat
= bswap32(old
->e2fs_features_rocompat
);
933 new->e2fs_algo
= bswap32(old
->e2fs_algo
);
934 new->e2fs_reserved_ngdb
= bswap16(old
->e2fs_reserved_ngdb
);
937 void e2fs_cg_bswap(struct ext2_gd
*old
, struct ext2_gd
*new, int size
)
941 for (i
= 0; i
< (size
/ sizeof(struct ext2_gd
)); i
++) {
942 new[i
].ext2bgd_b_bitmap
= bswap32(old
[i
].ext2bgd_b_bitmap
);
943 new[i
].ext2bgd_i_bitmap
= bswap32(old
[i
].ext2bgd_i_bitmap
);
944 new[i
].ext2bgd_i_tables
= bswap32(old
[i
].ext2bgd_i_tables
);
945 new[i
].ext2bgd_nbfree
= bswap16(old
[i
].ext2bgd_nbfree
);
946 new[i
].ext2bgd_nifree
= bswap16(old
[i
].ext2bgd_nifree
);
947 new[i
].ext2bgd_ndirs
= bswap16(old
[i
].ext2bgd_ndirs
);
951 void e2fs_i_bswap(struct ext2fs_dinode
*old
, struct ext2fs_dinode
*new)
954 new->e2di_mode
= bswap16(old
->e2di_mode
);
955 new->e2di_uid
= bswap16(old
->e2di_uid
);
956 new->e2di_gid
= bswap16(old
->e2di_gid
);
957 new->e2di_nlink
= bswap16(old
->e2di_nlink
);
958 new->e2di_size
= bswap32(old
->e2di_size
);
959 new->e2di_atime
= bswap32(old
->e2di_atime
);
960 new->e2di_ctime
= bswap32(old
->e2di_ctime
);
961 new->e2di_mtime
= bswap32(old
->e2di_mtime
);
962 new->e2di_dtime
= bswap32(old
->e2di_dtime
);
963 new->e2di_nblock
= bswap32(old
->e2di_nblock
);
964 new->e2di_flags
= bswap32(old
->e2di_flags
);
965 new->e2di_gen
= bswap32(old
->e2di_gen
);
966 new->e2di_facl
= bswap32(old
->e2di_facl
);
967 new->e2di_dacl
= bswap32(old
->e2di_dacl
);
968 new->e2di_faddr
= bswap32(old
->e2di_faddr
);
969 memcpy(&new->e2di_blocks
[0], &old
->e2di_blocks
[0],
970 (EXT2FS_NDADDR
+ EXT2FS_NIADDR
) * sizeof(uint32_t));
976 dump_sblock(struct m_ext2fs
*fs
)
979 printf("fs->e2fs.e2fs_bcount = %u\n", fs
->e2fs
.e2fs_bcount
);
980 printf("fs->e2fs.e2fs_first_dblock = %u\n", fs
->e2fs
.e2fs_first_dblock
);
981 printf("fs->e2fs.e2fs_log_bsize = %u\n", fs
->e2fs
.e2fs_log_bsize
);
982 printf("fs->e2fs.e2fs_bpg = %u\n", fs
->e2fs
.e2fs_bpg
);
983 printf("fs->e2fs.e2fs_ipg = %u\n", fs
->e2fs
.e2fs_ipg
);
984 printf("fs->e2fs.e2fs_magic = 0x%x\n", fs
->e2fs
.e2fs_magic
);
985 printf("fs->e2fs.e2fs_rev = %u\n", fs
->e2fs
.e2fs_rev
);
987 if (fs
->e2fs
.e2fs_rev
== E2FS_REV1
) {
988 printf("fs->e2fs.e2fs_first_ino = %u\n",
989 fs
->e2fs
.e2fs_first_ino
);
990 printf("fs->e2fs.e2fs_inode_size = %u\n",
991 fs
->e2fs
.e2fs_inode_size
);
992 printf("fs->e2fs.e2fs_features_compat = %u\n",
993 fs
->e2fs
.e2fs_features_compat
);
994 printf("fs->e2fs.e2fs_features_incompat = %u\n",
995 fs
->e2fs
.e2fs_features_incompat
);
996 printf("fs->e2fs.e2fs_features_rocompat = %u\n",
997 fs
->e2fs
.e2fs_features_rocompat
);
998 printf("fs->e2fs.e2fs_reserved_ngdb = %u\n",
999 fs
->e2fs
.e2fs_reserved_ngdb
);
1002 printf("fs->e2fs_bsize = %u\n", fs
->e2fs_bsize
);
1003 printf("fs->e2fs_fsbtodb = %u\n", fs
->e2fs_fsbtodb
);
1004 printf("fs->e2fs_ncg = %u\n", fs
->e2fs_ncg
);
1005 printf("fs->e2fs_ngdb = %u\n", fs
->e2fs_ngdb
);
1006 printf("fs->e2fs_ipb = %u\n", fs
->e2fs_ipb
);
1007 printf("fs->e2fs_itpg = %u\n", fs
->e2fs_itpg
);