blob: 43e8e6eb0c58810d41c67bbfd19e6306cbb9110f [file] [log] [blame]
"Robert P. J. Day"63fc1a92006-07-02 19:47:05 +00001/* vi: set sw=4 ts=4: */
Mike Frysinger1fd98e02005-05-09 22:10:42 +00002/*
3 * dirblock.c --- directory block routines.
Tim Rikerc1ef7bd2006-01-25 00:08:53 +00004 *
Mike Frysinger1fd98e02005-05-09 22:10:42 +00005 * 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
23errcode_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;
Mike Frysingere70aa9d2005-07-30 09:43:58 +000029 unsigned int name_len, rec_len;
Rob Landley7c94bed2006-05-03 21:58:45 +000030#if BB_BIG_ENDIAN
Mike Frysingere70aa9d2005-07-30 09:43:58 +000031 unsigned int do_swap;
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000032#endif
Mike Frysinger1fd98e02005-05-09 22:10:42 +000033
Tim Rikerc1ef7bd2006-01-25 00:08:53 +000034 retval = io_channel_read_blk(fs->io, block, 1, buf);
Mike Frysinger1fd98e02005-05-09 22:10:42 +000035 if (retval)
36 return retval;
Rob Landley7c94bed2006-05-03 21:58:45 +000037#if BB_BIG_ENDIAN
Mike Frysinger1fd98e02005-05-09 22:10:42 +000038 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;
Rob Landley7c94bed2006-05-03 21:58:45 +000045#if BB_BIG_ENDIAN
Mike Frysinger1fd98e02005-05-09 22:10:42 +000046 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
69errcode_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
76errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
77 void *inbuf, int flags EXT2FS_ATTR((unused)))
78{
Rob Landley7c94bed2006-05-03 21:58:45 +000079#if BB_BIG_ENDIAN
Mike Frysinger1fd98e02005-05-09 22:10:42 +000080 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 }
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000114#ifdef WORDS_BIGENDIAN
Mike Frysinger1fd98e02005-05-09 22:10:42 +0000115 if (flags & EXT2_DIRBLOCK_V2_STRUCT)
116 dirent->name_len = ext2fs_swab16(dirent->name_len);
117#endif
118 }
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000119 retval = io_channel_write_blk(fs->io, block, 1, buf);
Mike Frysinger1fd98e02005-05-09 22:10:42 +0000120 ext2fs_free_mem(&buf);
121 return retval;
122#else
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000123 return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
Mike Frysinger1fd98e02005-05-09 22:10:42 +0000124#endif
125}
126
127
128errcode_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