1 /* $NetBSD: ext2fs.c,v 1.7 2009/03/02 10:25:00 tsutsui 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) 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 */
149 static int read_inode(ino32_t
, struct open_file
*);
150 static int block_map(struct open_file
*, indp_t
, indp_t
*);
151 static int buf_read_file(struct open_file
*, char **, size_t *);
152 static int search_directory(const char *, int, struct open_file
*, ino32_t
*);
153 static int read_sblock(struct open_file
*, struct m_ext2fs
*);
154 static int read_gdblock(struct open_file
*, struct m_ext2fs
*);
156 static void dump_sblock(struct m_ext2fs
*);
160 * Read a new inode into a file structure.
163 read_inode(ino32_t inumber
, struct open_file
*f
)
165 struct file
*fp
= (struct file
*)f
->f_fsdata
;
166 struct m_ext2fs
*fs
= fp
->f_fs
;
170 daddr_t inode_sector
;
171 struct ext2fs_dinode
*dip
;
173 inode_sector
= FSBTODB(fs
, ino_to_fsba(fs
, inumber
));
176 * Read inode and save it.
180 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
181 inode_sector
, fs
->e2fs_bsize
, buf
, &rsize
);
184 if (rsize
!= fs
->e2fs_bsize
)
187 dip
= (struct ext2fs_dinode
*)(buf
+
188 EXT2_DINODE_SIZE(fs
) * ino_to_fsbo(fs
, inumber
));
189 e2fs_iload(dip
, &fp
->f_di
);
192 * Clear out the old buffers
194 fp
->f_ind_cache_block
= ~0;
195 fp
->f_buf_blkno
= -1;
200 * Given an offset in a file, find the disk block number that
201 * contains that block.
204 block_map(struct open_file
*f
, indp_t file_block
, indp_t
*disk_block_p
)
206 struct file
*fp
= (struct file
*)f
->f_fsdata
;
207 struct m_ext2fs
*fs
= fp
->f_fs
;
210 indp_t ind_block_num
;
213 indp_t
*buf
= (void *)fp
->f_buf
;
216 * Index structure of an inode:
218 * e2di_blocks[0..NDADDR-1]
219 * hold block numbers for blocks
222 * e2di_blocks[NDADDR+0]
223 * block NDADDR+0 is the single indirect block
224 * holds block numbers for blocks
225 * NDADDR .. NDADDR + NINDIR(fs)-1
227 * e2di_blocks[NDADDR+1]
228 * block NDADDR+1 is the double indirect block
229 * holds block numbers for INDEX blocks for blocks
230 * NDADDR + NINDIR(fs) ..
231 * NDADDR + NINDIR(fs) + NINDIR(fs)**2 - 1
233 * e2di_blocks[NDADDR+2]
234 * block NDADDR+2 is the triple indirect block
235 * holds block numbers for double-indirect
237 * NDADDR + NINDIR(fs) + NINDIR(fs)**2 ..
238 * NDADDR + NINDIR(fs) + NINDIR(fs)**2
239 * + NINDIR(fs)**3 - 1
242 if (file_block
< NDADDR
) {
244 *disk_block_p
= fs2h32(fp
->f_di
.e2di_blocks
[file_block
]);
248 file_block
-= NDADDR
;
250 ind_cache
= file_block
>> LN2_IND_CACHE_SZ
;
251 if (ind_cache
== fp
->f_ind_cache_block
) {
253 fs2h32(fp
->f_ind_cache
[file_block
& IND_CACHE_MASK
]);
258 level
+= fp
->f_nishift
;
259 if (file_block
< (indp_t
)1 << level
)
261 if (level
> NIADDR
* fp
->f_nishift
)
262 /* Block number too high */
264 file_block
-= (indp_t
)1 << level
;
268 fs2h32(fp
->f_di
.e2di_blocks
[NDADDR
+ (level
/ fp
->f_nishift
- 1)]);
271 level
-= fp
->f_nishift
;
272 if (ind_block_num
== 0) {
273 *disk_block_p
= 0; /* missing */
279 * If we were feeling brave, we could work out the number
280 * of the disk sector and read a single disk sector instead
281 * of a filesystem block.
282 * However we don't do this very often anyway...
284 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
285 FSBTODB(fp
->f_fs
, ind_block_num
), fs
->e2fs_bsize
,
289 if (rsize
!= fs
->e2fs_bsize
)
291 ind_block_num
= fs2h32(buf
[file_block
>> level
]);
294 file_block
&= (1 << level
) - 1;
297 /* Save the part of the block that contains this sector */
298 memcpy(fp
->f_ind_cache
, &buf
[file_block
& ~IND_CACHE_MASK
],
299 IND_CACHE_SZ
* sizeof fp
->f_ind_cache
[0]);
300 fp
->f_ind_cache_block
= ind_cache
;
302 *disk_block_p
= ind_block_num
;
308 * Read a portion of a file into an internal buffer.
309 * Return the location in the buffer and the amount in the buffer.
312 buf_read_file(struct open_file
*f
, char **buf_p
, size_t *size_p
)
314 struct file
*fp
= (struct file
*)f
->f_fsdata
;
315 struct m_ext2fs
*fs
= fp
->f_fs
;
322 off
= blkoff(fs
, fp
->f_seekp
);
323 file_block
= lblkno(fs
, fp
->f_seekp
);
324 block_size
= fs
->e2fs_bsize
; /* no fragment */
326 if (file_block
!= fp
->f_buf_blkno
) {
327 rc
= block_map(f
, file_block
, &disk_block
);
331 if (disk_block
== 0) {
332 memset(fp
->f_buf
, 0, block_size
);
333 fp
->f_buf_size
= block_size
;
336 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
337 FSBTODB(fs
, disk_block
),
338 block_size
, fp
->f_buf
, &fp
->f_buf_size
);
343 fp
->f_buf_blkno
= file_block
;
347 * Return address of byte in buffer corresponding to
348 * offset, and size of remainder of buffer after that
351 *buf_p
= fp
->f_buf
+ off
;
352 *size_p
= block_size
- off
;
355 * But truncate buffer at end of file.
357 /* XXX should handle LARGEFILE */
358 if (*size_p
> fp
->f_di
.e2di_size
- fp
->f_seekp
)
359 *size_p
= fp
->f_di
.e2di_size
- fp
->f_seekp
;
365 * Search a directory for a name and return its
369 search_directory(const char *name
, int length
, struct open_file
*f
,
372 struct file
*fp
= (struct file
*)f
->f_fsdata
;
373 struct ext2fs_direct
*dp
;
374 struct ext2fs_direct
*edp
;
381 /* XXX should handle LARGEFILE */
382 while (fp
->f_seekp
< (off_t
)fp
->f_di
.e2di_size
) {
383 rc
= buf_read_file(f
, &buf
, &buf_size
);
387 dp
= (struct ext2fs_direct
*)buf
;
388 edp
= (struct ext2fs_direct
*)(buf
+ buf_size
);
390 dp
= (void *)((char *)dp
+ fs2h16(dp
->e2d_reclen
))) {
391 if (fs2h16(dp
->e2d_reclen
) <= 0)
393 if (fs2h32(dp
->e2d_ino
) == (ino32_t
)0)
395 namlen
= dp
->e2d_namlen
;
396 if (namlen
== length
&&
397 !memcmp(name
, dp
->e2d_name
, length
)) {
399 *inumber_p
= fs2h32(dp
->e2d_ino
);
403 fp
->f_seekp
+= buf_size
;
409 read_sblock(struct open_file
*f
, struct m_ext2fs
*fs
)
411 static uint8_t sbbuf
[SBSIZE
];
412 struct ext2fs ext2fs
;
416 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
417 SBOFF
/ DEV_BSIZE
, SBSIZE
, sbbuf
, &buf_size
);
421 if (buf_size
!= SBSIZE
)
424 e2fs_sbload((void *)sbbuf
, &ext2fs
);
425 if (ext2fs
.e2fs_magic
!= E2FS_MAGIC
)
427 if (ext2fs
.e2fs_rev
> E2FS_REV1
||
428 (ext2fs
.e2fs_rev
== E2FS_REV1
&&
429 (ext2fs
.e2fs_first_ino
!= EXT2_FIRSTINO
||
430 (ext2fs
.e2fs_inode_size
!= 128 && ext2fs
.e2fs_inode_size
!= 256) ||
431 ext2fs
.e2fs_features_incompat
& ~EXT2F_INCOMPAT_SUPP
))) {
435 e2fs_sbload((void *)sbbuf
, &fs
->e2fs
);
436 /* compute in-memory m_ext2fs values */
438 howmany(fs
->e2fs
.e2fs_bcount
- fs
->e2fs
.e2fs_first_dblock
,
440 /* XXX assume hw bsize = 512 */
441 fs
->e2fs_fsbtodb
= fs
->e2fs
.e2fs_log_bsize
+ 1;
442 fs
->e2fs_bsize
= MINBSIZE
<< fs
->e2fs
.e2fs_log_bsize
;
443 fs
->e2fs_bshift
= LOG_MINBSIZE
+ fs
->e2fs
.e2fs_log_bsize
;
444 fs
->e2fs_qbmask
= fs
->e2fs_bsize
- 1;
445 fs
->e2fs_bmask
= ~fs
->e2fs_qbmask
;
447 howmany(fs
->e2fs_ncg
, fs
->e2fs_bsize
/ sizeof(struct ext2_gd
));
448 fs
->e2fs_ipb
= fs
->e2fs_bsize
/ ext2fs
.e2fs_inode_size
;
449 fs
->e2fs_itpg
= fs
->e2fs
.e2fs_ipg
/ fs
->e2fs_ipb
;
455 read_gdblock(struct open_file
*f
, struct m_ext2fs
*fs
)
457 struct file
*fp
= (struct file
*)f
->f_fsdata
;
462 gdpb
= fs
->e2fs_bsize
/ sizeof(struct ext2_gd
);
464 for (i
= 0; i
< fs
->e2fs_ngdb
; i
++) {
465 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
, F_READ
,
466 FSBTODB(fs
, fs
->e2fs
.e2fs_first_dblock
+
467 1 /* superblock */ + i
),
468 fs
->e2fs_bsize
, fp
->f_buf
, &rsize
);
471 if (rsize
!= fs
->e2fs_bsize
)
474 e2fs_cgload((struct ext2_gd
*)fp
->f_buf
,
475 &fs
->e2fs_gd
[i
* gdpb
],
476 (i
== (fs
->e2fs_ngdb
- 1)) ?
477 (fs
->e2fs_ncg
- gdpb
* i
) * sizeof(struct ext2_gd
):
489 ext2fs_open(const char *path
, struct open_file
*f
)
491 #ifndef LIBSA_FS_SINGLECOMPONENT
492 const char *cp
, *ncp
;
499 #ifndef LIBSA_NO_FS_SYMLINK
500 ino32_t parent_inumber
;
502 char namebuf
[MAXPATHLEN
+1];
506 /* allocate file system specific data structure */
507 fp
= alloc(sizeof(struct file
));
508 memset(fp
, 0, sizeof(struct file
));
509 f
->f_fsdata
= (void *)fp
;
511 /* allocate space and read super block */
512 fs
= alloc(sizeof(*fs
));
516 rc
= read_sblock(f
, fs
);
524 /* alloc a block sized buffer used for all fs transfers */
525 fp
->f_buf
= alloc(fs
->e2fs_bsize
);
527 /* read group descriptor blocks */
528 fs
->e2fs_gd
= alloc(sizeof(struct ext2_gd
) * fs
->e2fs_ncg
);
529 rc
= read_gdblock(f
, fs
);
534 * Calculate indirect block levels.
541 * We note that the number of indirect blocks is always
542 * a power of 2. This lets us use shifts and masks instead
543 * of divide and remainder and avoinds pulling in the
544 * 64bit division routine into the boot code.
548 if (!powerof2(mult
)) {
549 /* Hummm was't a power of 2 */
554 for (ln2
= 0; mult
!= 1; ln2
++)
560 inumber
= EXT2_ROOTINO
;
561 if ((rc
= read_inode(inumber
, f
)) != 0)
564 #ifndef LIBSA_FS_SINGLECOMPONENT
569 * Remove extra separators
577 * Check that current node is a directory.
579 if ((fp
->f_di
.e2di_mode
& EXT2_IFMT
) != EXT2_IFDIR
) {
585 * Get next component of path name.
588 while ((c
= *cp
) != '\0' && c
!= '/')
592 * Look up component in current directory.
593 * Save directory inumber in case we find a
596 #ifndef LIBSA_NO_FS_SYMLINK
597 parent_inumber
= inumber
;
599 rc
= search_directory(ncp
, cp
- ncp
, f
, &inumber
);
604 * Open next component.
606 if ((rc
= read_inode(inumber
, f
)) != 0)
609 #ifndef LIBSA_NO_FS_SYMLINK
611 * Check for symbolic link.
613 if ((fp
->f_di
.e2di_mode
& EXT2_IFMT
) == EXT2_IFLNK
) {
614 /* XXX should handle LARGEFILE */
615 int link_len
= fp
->f_di
.e2di_size
;
620 if (link_len
+ len
> MAXPATHLEN
||
621 ++nlinks
> MAXSYMLINKS
) {
626 memmove(&namebuf
[link_len
], cp
, len
+ 1);
628 if (link_len
< EXT2_MAXSYMLINKLEN
) {
629 memcpy(namebuf
, fp
->f_di
.e2di_blocks
, link_len
);
632 * Read file for symbolic link
638 rc
= block_map(f
, (indp_t
)0, &disk_block
);
643 rc
= DEV_STRATEGY(f
->f_dev
)(f
->f_devdata
,
644 F_READ
, FSBTODB(fs
, disk_block
),
645 fs
->e2fs_bsize
, buf
, &buf_size
);
649 memcpy(namebuf
, buf
, link_len
);
653 * If relative pathname, restart at parent directory.
654 * If absolute pathname, restart at root.
658 inumber
= parent_inumber
;
660 inumber
= (ino32_t
)EXT2_ROOTINO
;
662 if ((rc
= read_inode(inumber
, f
)) != 0)
665 #endif /* !LIBSA_NO_FS_SYMLINK */
669 * Found terminal component.
673 #else /* !LIBSA_FS_SINGLECOMPONENT */
675 /* look up component in the current (root) directory */
676 rc
= search_directory(path
, strlen(path
), f
, &inumber
);
681 rc
= read_inode(inumber
, f
);
683 #endif /* !LIBSA_FS_SINGLECOMPONENT */
685 fp
->f_seekp
= 0; /* reset seek pointer */
698 ext2fs_close(struct open_file
*f
)
700 struct file
*fp
= (struct file
*)f
->f_fsdata
;
706 if (fp
->f_fs
->e2fs_gd
)
707 dealloc(fp
->f_fs
->e2fs_gd
,
708 sizeof(struct ext2_gd
) * fp
->f_fs
->e2fs_ncg
);
710 dealloc(fp
->f_buf
, fp
->f_fs
->e2fs_bsize
);
711 dealloc(fp
->f_fs
, sizeof(*fp
->f_fs
));
712 dealloc(fp
, sizeof(struct file
));
717 * Copy a portion of a file into kernel memory.
718 * Cross block boundaries when necessary.
721 ext2fs_read(struct open_file
*f
, void *start
, size_t size
, size_t *resid
)
723 struct file
*fp
= (struct file
*)f
->f_fsdata
;
731 /* XXX should handle LARGEFILE */
732 if (fp
->f_seekp
>= (off_t
)fp
->f_di
.e2di_size
)
735 rc
= buf_read_file(f
, &buf
, &buf_size
);
740 if (csize
> buf_size
)
743 memcpy(addr
, buf
, csize
);
745 fp
->f_seekp
+= csize
;
757 #ifndef LIBSA_NO_FS_WRITE
759 ext2fs_write(struct open_file
*f
, void *start
, size_t size
, size_t *resid
)
764 #endif /* !LIBSA_NO_FS_WRITE */
766 #ifndef LIBSA_NO_FS_SEEK
768 ext2fs_seek(struct open_file
*f
, off_t offset
, int where
)
770 struct file
*fp
= (struct file
*)f
->f_fsdata
;
774 fp
->f_seekp
= offset
;
777 fp
->f_seekp
+= offset
;
780 /* XXX should handle LARGEFILE */
781 fp
->f_seekp
= fp
->f_di
.e2di_size
- offset
;
788 #endif /* !LIBSA_NO_FS_SEEK */
791 ext2fs_stat(struct open_file
*f
, struct stat
*sb
)
793 struct file
*fp
= (struct file
*)f
->f_fsdata
;
795 /* only important stuff */
796 memset(sb
, 0, sizeof *sb
);
797 sb
->st_mode
= fp
->f_di
.e2di_mode
;
798 sb
->st_uid
= fp
->f_di
.e2di_uid
;
799 sb
->st_gid
= fp
->f_di
.e2di_gid
;
800 /* XXX should handle LARGEFILE */
801 sb
->st_size
= fp
->f_di
.e2di_size
;
806 * byte swap functions for big endian machines
807 * (ext2fs is always little endian)
809 * XXX: We should use src/sys/ufs/ext2fs/ext2fs_bswap.c
812 /* These functions are only needed if native byte order is not big endian */
813 #if BYTE_ORDER == BIG_ENDIAN
815 e2fs_sb_bswap(struct ext2fs
*old
, struct ext2fs
*new)
818 /* preserve unused fields */
819 memcpy(new, old
, sizeof(struct ext2fs
));
820 new->e2fs_icount
= bswap32(old
->e2fs_icount
);
821 new->e2fs_bcount
= bswap32(old
->e2fs_bcount
);
822 new->e2fs_rbcount
= bswap32(old
->e2fs_rbcount
);
823 new->e2fs_fbcount
= bswap32(old
->e2fs_fbcount
);
824 new->e2fs_ficount
= bswap32(old
->e2fs_ficount
);
825 new->e2fs_first_dblock
= bswap32(old
->e2fs_first_dblock
);
826 new->e2fs_log_bsize
= bswap32(old
->e2fs_log_bsize
);
827 new->e2fs_fsize
= bswap32(old
->e2fs_fsize
);
828 new->e2fs_bpg
= bswap32(old
->e2fs_bpg
);
829 new->e2fs_fpg
= bswap32(old
->e2fs_fpg
);
830 new->e2fs_ipg
= bswap32(old
->e2fs_ipg
);
831 new->e2fs_mtime
= bswap32(old
->e2fs_mtime
);
832 new->e2fs_wtime
= bswap32(old
->e2fs_wtime
);
833 new->e2fs_mnt_count
= bswap16(old
->e2fs_mnt_count
);
834 new->e2fs_max_mnt_count
= bswap16(old
->e2fs_max_mnt_count
);
835 new->e2fs_magic
= bswap16(old
->e2fs_magic
);
836 new->e2fs_state
= bswap16(old
->e2fs_state
);
837 new->e2fs_beh
= bswap16(old
->e2fs_beh
);
838 new->e2fs_minrev
= bswap16(old
->e2fs_minrev
);
839 new->e2fs_lastfsck
= bswap32(old
->e2fs_lastfsck
);
840 new->e2fs_fsckintv
= bswap32(old
->e2fs_fsckintv
);
841 new->e2fs_creator
= bswap32(old
->e2fs_creator
);
842 new->e2fs_rev
= bswap32(old
->e2fs_rev
);
843 new->e2fs_ruid
= bswap16(old
->e2fs_ruid
);
844 new->e2fs_rgid
= bswap16(old
->e2fs_rgid
);
845 new->e2fs_first_ino
= bswap32(old
->e2fs_first_ino
);
846 new->e2fs_inode_size
= bswap16(old
->e2fs_inode_size
);
847 new->e2fs_block_group_nr
= bswap16(old
->e2fs_block_group_nr
);
848 new->e2fs_features_compat
= bswap32(old
->e2fs_features_compat
);
849 new->e2fs_features_incompat
= bswap32(old
->e2fs_features_incompat
);
850 new->e2fs_features_rocompat
= bswap32(old
->e2fs_features_rocompat
);
851 new->e2fs_algo
= bswap32(old
->e2fs_algo
);
852 new->e2fs_reserved_ngdb
= bswap16(old
->e2fs_reserved_ngdb
);
855 void e2fs_cg_bswap(struct ext2_gd
*old
, struct ext2_gd
*new, int size
)
859 for (i
= 0; i
< (size
/ sizeof(struct ext2_gd
)); i
++) {
860 new[i
].ext2bgd_b_bitmap
= bswap32(old
[i
].ext2bgd_b_bitmap
);
861 new[i
].ext2bgd_i_bitmap
= bswap32(old
[i
].ext2bgd_i_bitmap
);
862 new[i
].ext2bgd_i_tables
= bswap32(old
[i
].ext2bgd_i_tables
);
863 new[i
].ext2bgd_nbfree
= bswap16(old
[i
].ext2bgd_nbfree
);
864 new[i
].ext2bgd_nifree
= bswap16(old
[i
].ext2bgd_nifree
);
865 new[i
].ext2bgd_ndirs
= bswap16(old
[i
].ext2bgd_ndirs
);
869 void e2fs_i_bswap(struct ext2fs_dinode
*old
, struct ext2fs_dinode
*new)
872 new->e2di_mode
= bswap16(old
->e2di_mode
);
873 new->e2di_uid
= bswap16(old
->e2di_uid
);
874 new->e2di_gid
= bswap16(old
->e2di_gid
);
875 new->e2di_nlink
= bswap16(old
->e2di_nlink
);
876 new->e2di_size
= bswap32(old
->e2di_size
);
877 new->e2di_atime
= bswap32(old
->e2di_atime
);
878 new->e2di_ctime
= bswap32(old
->e2di_ctime
);
879 new->e2di_mtime
= bswap32(old
->e2di_mtime
);
880 new->e2di_dtime
= bswap32(old
->e2di_dtime
);
881 new->e2di_nblock
= bswap32(old
->e2di_nblock
);
882 new->e2di_flags
= bswap32(old
->e2di_flags
);
883 new->e2di_gen
= bswap32(old
->e2di_gen
);
884 new->e2di_facl
= bswap32(old
->e2di_facl
);
885 new->e2di_dacl
= bswap32(old
->e2di_dacl
);
886 new->e2di_faddr
= bswap32(old
->e2di_faddr
);
887 memcpy(&new->e2di_blocks
[0], &old
->e2di_blocks
[0],
888 (NDADDR
+ NIADDR
) * sizeof(uint32_t));
894 dump_sblock(struct m_ext2fs
*fs
)
897 printf("fs->e2fs.e2fs_bcount = %u\n", fs
->e2fs
.e2fs_bcount
);
898 printf("fs->e2fs.e2fs_first_dblock = %u\n", fs
->e2fs
.e2fs_first_dblock
);
899 printf("fs->e2fs.e2fs_log_bsize = %u\n", fs
->e2fs
.e2fs_log_bsize
);
900 printf("fs->e2fs.e2fs_bpg = %u\n", fs
->e2fs
.e2fs_bpg
);
901 printf("fs->e2fs.e2fs_ipg = %u\n", fs
->e2fs
.e2fs_ipg
);
902 printf("fs->e2fs.e2fs_magic = 0x%x\n", fs
->e2fs
.e2fs_magic
);
903 printf("fs->e2fs.e2fs_rev = %u\n", fs
->e2fs
.e2fs_rev
);
905 if (fs
->e2fs
.e2fs_rev
== E2FS_REV1
) {
906 printf("fs->e2fs.e2fs_first_ino = %u\n",
907 fs
->e2fs
.e2fs_first_ino
);
908 printf("fs->e2fs.e2fs_inode_size = %u\n",
909 fs
->e2fs
.e2fs_inode_size
);
910 printf("fs->e2fs.e2fs_features_compat = %u\n",
911 fs
->e2fs
.e2fs_features_compat
);
912 printf("fs->e2fs.e2fs_features_incompat = %u\n",
913 fs
->e2fs
.e2fs_features_incompat
);
914 printf("fs->e2fs.e2fs_features_rocompat = %u\n",
915 fs
->e2fs
.e2fs_features_rocompat
);
916 printf("fs->e2fs.e2fs_reserved_ngdb = %u\n",
917 fs
->e2fs
.e2fs_reserved_ngdb
);
920 printf("fs->e2fs_bsize = %u\n", fs
->e2fs_bsize
);
921 printf("fs->e2fs_fsbtodb = %u\n", fs
->e2fs_fsbtodb
);
922 printf("fs->e2fs_ncg = %u\n", fs
->e2fs_ncg
);
923 printf("fs->e2fs_ngdb = %u\n", fs
->e2fs_ngdb
);
924 printf("fs->e2fs_ipb = %u\n", fs
->e2fs_ipb
);
925 printf("fs->e2fs_itpg = %u\n", fs
->e2fs_itpg
);