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