blob: dd9fe5f197cdf8eec101585e54050c1424e30590 [file] [log] [blame]
Theodore Ts'o50e1e101997-04-26 13:58:21 +00001/*
2 * dirblock.c --- directory block routines.
3 *
Theodore Ts'o21c84b71997-04-29 16:15:03 +00004 * 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%
Theodore Ts'o50e1e101997-04-26 13:58:21 +000010 */
11
12#include <stdio.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000013#if HAVE_UNISTD_H
Theodore Ts'o50e1e101997-04-26 13:58:21 +000014#include <unistd.h>
Theodore Ts'o4cbe8af1997-08-10 23:07:40 +000015#endif
Theodore Ts'o21c84b71997-04-29 16:15:03 +000016#include <string.h>
Theodore Ts'o50e1e101997-04-26 13:58:21 +000017#include <time.h>
Theodore Ts'o50e1e101997-04-26 13:58:21 +000018
Theodore Ts'ob5abe6f1998-01-19 14:47:53 +000019#if EXT2_FLAT_INCLUDES
20#include "ext2_fs.h"
21#else
Theodore Ts'o50e1e101997-04-26 13:58:21 +000022#include <linux/ext2_fs.h>
Theodore Ts'ob5abe6f1998-01-19 14:47:53 +000023#endif
Theodore Ts'o50e1e101997-04-26 13:58:21 +000024
25#include "ext2fs.h"
26
27errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
28 void *buf)
29{
30 errcode_t retval;
31 char *p, *end;
32 struct ext2_dir_entry *dirent;
Theodore Ts'o1cca4d62001-05-05 05:12:14 +000033 struct ext2_dir_entry_2 *dirent2;
34 unsigned int rec_len, do_swap;
Theodore Ts'o50e1e101997-04-26 13:58:21 +000035
36 retval = io_channel_read_blk(fs->io, block, 1, buf);
37 if (retval)
38 return retval;
Theodore Ts'o1cca4d62001-05-05 05:12:14 +000039 do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
40 EXT2_FLAG_SWAP_BYTES_READ)) != 0;
Theodore Ts'ob5abe6f1998-01-19 14:47:53 +000041 p = (char *) buf;
Theodore Ts'o50e1e101997-04-26 13:58:21 +000042 end = (char *) buf + fs->blocksize;
Theodore Ts'oe446d712001-01-05 22:27:06 +000043 while (p < end-8) {
Theodore Ts'o1cca4d62001-05-05 05:12:14 +000044 dirent = (struct ext2_dir_entry_2 *) p;
45 if (do_swap) {
46 dirent->inode = ext2fs_swab32(dirent->inode);
47 dirent->rec_len = ext2fs_swab16(dirent->rec_len);
48 dirent->name_len = ext2fs_swab16(dirent->name_len);
49 }
50 rec_len = dirent->rec_len;
51 if ((rec_len < 8) || (rec_len % 4)) {
52 rec_len = 8;
53 retval = EXT2_ET_DIR_CORRUPTED;
54 }
55 dirent2 = dirent;
56 if ((dirent2->name_len +8) > dirent2->rec_len)
57 retval = EXT2_ET_DIR_CORRUPTED;
58 p += rec_len;
Theodore Ts'o50e1e101997-04-26 13:58:21 +000059 }
Theodore Ts'o1cca4d62001-05-05 05:12:14 +000060 return retval;
Theodore Ts'o50e1e101997-04-26 13:58:21 +000061}
62
63errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
64 void *inbuf)
65{
66 errcode_t retval;
67 char *p, *end, *write_buf;
68 char *buf = 0;
69 struct ext2_dir_entry *dirent;
70
Theodore Ts'o5c576471997-04-29 15:29:49 +000071 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
72 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) {
Theodore Ts'o7b4e4531997-10-26 03:41:24 +000073 retval = ext2fs_get_mem(fs->blocksize, (void **) &buf);
74 if (retval)
75 return retval;
76 write_buf = buf;
Theodore Ts'o50e1e101997-04-26 13:58:21 +000077 memcpy(buf, inbuf, fs->blocksize);
78 p = buf;
79 end = buf + fs->blocksize;
80 while (p < end) {
81 dirent = (struct ext2_dir_entry *) p;
Theodore Ts'o1cca4d62001-05-05 05:12:14 +000082 if ((dirent->rec_len < 8) ||
83 (dirent->rec_len % 4)) {
84 retval = EXT2_ET_DIR_CORRUPTED;
85 goto errout;
86 }
87 p += dirent->rec_len;
Theodore Ts'o50e1e101997-04-26 13:58:21 +000088 dirent->inode = ext2fs_swab32(dirent->inode);
89 dirent->rec_len = ext2fs_swab16(dirent->rec_len);
90 dirent->name_len = ext2fs_swab16(dirent->name_len);
91 }
92 } else
Theodore Ts'ob5abe6f1998-01-19 14:47:53 +000093 write_buf = (char *) inbuf;
Theodore Ts'o50e1e101997-04-26 13:58:21 +000094 retval = io_channel_write_blk(fs->io, block, 1, write_buf);
Theodore Ts'o1cca4d62001-05-05 05:12:14 +000095errout:
Theodore Ts'o50e1e101997-04-26 13:58:21 +000096 if (buf)
Theodore Ts'o7b4e4531997-10-26 03:41:24 +000097 ext2fs_free_mem((void **) &buf);
Theodore Ts'o50e1e101997-04-26 13:58:21 +000098 return retval;
99}
100
101