OSDN Git Service

Code drop from //branches/cupcake/...@124589
[android-x86/external-e2fsprogs.git] / lib / ext2fs / dirblock.c
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
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
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
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
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