• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * dirblock.c --- directory block routines.
3  *
4  * Copyright (C) 1995, 1996 Theodore Ts'o.
5  *
6  * %Begin-Header%
7  * This file may be redistributed under the terms of the GNU Public
8  * License.
9  * %End-Header%
10  */
11 
12 #include <stdio.h>
13 #if HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16 #include <string.h>
17 #include <time.h>
18 
19 #include "ext2_fs.h"
20 #include "ext2fs.h"
21 
ext2fs_read_dir_block2(ext2_filsys fs,blk_t block,void * buf,int flags EXT2FS_ATTR ((unused)))22 errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
23 				 void *buf, int flags EXT2FS_ATTR((unused)))
24 {
25 	errcode_t	retval;
26 	char		*p, *end;
27 	struct ext2_dir_entry *dirent;
28 	unsigned int	name_len, rec_len, do_swap;
29 
30 
31  	retval = io_channel_read_blk(fs->io, block, 1, buf);
32 	if (retval)
33 		return retval;
34 #ifdef EXT2FS_ENABLE_SWAPFS
35 	do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
36 				EXT2_FLAG_SWAP_BYTES_READ)) != 0;
37 #endif
38 	p = (char *) buf;
39 	end = (char *) buf + fs->blocksize;
40 	while (p < end-8) {
41 		dirent = (struct ext2_dir_entry *) p;
42 #ifdef EXT2FS_ENABLE_SWAPFS
43 		if (do_swap) {
44 			dirent->inode = ext2fs_swab32(dirent->inode);
45 			dirent->rec_len = ext2fs_swab16(dirent->rec_len);
46 			dirent->name_len = ext2fs_swab16(dirent->name_len);
47 		}
48 #endif
49 		name_len = dirent->name_len;
50 #ifdef WORDS_BIGENDIAN
51 		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
52 			dirent->name_len = ext2fs_swab16(dirent->name_len);
53 #endif
54 		rec_len = dirent->rec_len;
55 		if ((rec_len < 8) || (rec_len % 4)) {
56 			rec_len = 8;
57 			retval = EXT2_ET_DIR_CORRUPTED;
58 		}
59 		if (((name_len & 0xFF) + 8) > dirent->rec_len)
60 			retval = EXT2_ET_DIR_CORRUPTED;
61 		p += rec_len;
62 	}
63 	return retval;
64 }
65 
ext2fs_read_dir_block(ext2_filsys fs,blk_t block,void * buf)66 errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
67 				 void *buf)
68 {
69 	return ext2fs_read_dir_block2(fs, block, buf, 0);
70 }
71 
72 
ext2fs_write_dir_block2(ext2_filsys fs,blk_t block,void * inbuf,int flags EXT2FS_ATTR ((unused)))73 errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
74 				  void *inbuf, int flags EXT2FS_ATTR((unused)))
75 {
76 #ifdef EXT2FS_ENABLE_SWAPFS
77 	int		do_swap = 0;
78 	errcode_t	retval;
79 	char		*p, *end;
80 	char		*buf = 0;
81 	struct ext2_dir_entry *dirent;
82 
83 	if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
84 	    (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
85 		do_swap = 1;
86 
87 #ifndef WORDS_BIGENDIAN
88 	if (!do_swap)
89 		return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
90 #endif
91 
92 	retval = ext2fs_get_mem(fs->blocksize, &buf);
93 	if (retval)
94 		return retval;
95 	memcpy(buf, inbuf, fs->blocksize);
96 	p = buf;
97 	end = buf + fs->blocksize;
98 	while (p < end) {
99 		dirent = (struct ext2_dir_entry *) p;
100 		if ((dirent->rec_len < 8) ||
101 		    (dirent->rec_len % 4)) {
102 			ext2fs_free_mem(&buf);
103 			return (EXT2_ET_DIR_CORRUPTED);
104 		}
105 		p += dirent->rec_len;
106 		if (do_swap) {
107 			dirent->inode = ext2fs_swab32(dirent->inode);
108 			dirent->rec_len = ext2fs_swab16(dirent->rec_len);
109 			dirent->name_len = ext2fs_swab16(dirent->name_len);
110 		}
111 #ifdef WORDS_BIGENDIAN
112 		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
113 			dirent->name_len = ext2fs_swab16(dirent->name_len);
114 #endif
115 	}
116  	retval = io_channel_write_blk(fs->io, block, 1, buf);
117 	ext2fs_free_mem(&buf);
118 	return retval;
119 #else
120  	return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
121 #endif
122 }
123 
124 
ext2fs_write_dir_block(ext2_filsys fs,blk_t block,void * inbuf)125 errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
126 				 void *inbuf)
127 {
128 	return ext2fs_write_dir_block2(fs, block, inbuf, 0);
129 }
130 
131