dirblock.c revision d1154eb460efe588eaed3d439c1caaca149fa362
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 Library
8 * General Public License, version 2.
9 * %End-Header%
10 */
11
12#include "config.h"
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_block3(ext2_filsys fs, blk64_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
31
32	retval = io_channel_read_blk64(fs->io, block, 1, buf);
33	if (retval)
34		return retval;
35
36	p = (char *) buf;
37	end = (char *) buf + fs->blocksize;
38	while (p < end-8) {
39		dirent = (struct ext2_dir_entry *) p;
40#ifdef WORDS_BIGENDIAN
41		dirent->inode = ext2fs_swab32(dirent->inode);
42		dirent->rec_len = ext2fs_swab16(dirent->rec_len);
43		dirent->name_len = ext2fs_swab16(dirent->name_len);
44#endif
45		name_len = dirent->name_len;
46#ifdef WORDS_BIGENDIAN
47		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
48			dirent->name_len = ext2fs_swab16(dirent->name_len);
49#endif
50		if ((retval = ext2fs_get_rec_len(fs, dirent, &rec_len)) != 0)
51			return retval;
52		if ((rec_len < 8) || (rec_len % 4)) {
53			rec_len = 8;
54			retval = EXT2_ET_DIR_CORRUPTED;
55		} else if (((name_len & 0xFF) + 8) > rec_len)
56			retval = EXT2_ET_DIR_CORRUPTED;
57		p += rec_len;
58	}
59	return retval;
60}
61
62errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
63				 void *buf, int flags EXT2FS_ATTR((unused)))
64{
65	return ext2fs_read_dir_block3(fs, block, buf, flags);
66}
67
68errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
69				 void *buf)
70{
71	return ext2fs_read_dir_block3(fs, block, buf, 0);
72}
73
74
75errcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
76				  void *inbuf, int flags EXT2FS_ATTR((unused)))
77{
78#ifdef WORDS_BIGENDIAN
79	errcode_t	retval;
80	char		*p, *end;
81	char		*buf = 0;
82	unsigned int	rec_len;
83	struct ext2_dir_entry *dirent;
84
85	retval = ext2fs_get_mem(fs->blocksize, &buf);
86	if (retval)
87		return retval;
88	memcpy(buf, inbuf, fs->blocksize);
89	p = buf;
90	end = buf + fs->blocksize;
91	while (p < end) {
92		dirent = (struct ext2_dir_entry *) p;
93		if ((retval = ext2fs_get_rec_len(fs, dirent, &rec_len)) != 0)
94			return retval;
95		if ((rec_len < 8) ||
96		    (rec_len % 4)) {
97			ext2fs_free_mem(&buf);
98			return (EXT2_ET_DIR_CORRUPTED);
99		}
100		p += rec_len;
101		dirent->inode = ext2fs_swab32(dirent->inode);
102		dirent->rec_len = ext2fs_swab16(dirent->rec_len);
103		dirent->name_len = ext2fs_swab16(dirent->name_len);
104
105		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
106			dirent->name_len = ext2fs_swab16(dirent->name_len);
107	}
108	retval = io_channel_write_blk64(fs->io, block, 1, buf);
109	ext2fs_free_mem(&buf);
110	return retval;
111#else
112	return io_channel_write_blk64(fs->io, block, 1, (char *) inbuf);
113#endif
114}
115
116errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
117				 void *inbuf, int flags EXT2FS_ATTR((unused)))
118{
119	return ext2fs_write_dir_block3(fs, block, inbuf, flags);
120}
121
122errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
123				 void *inbuf)
124{
125	return ext2fs_write_dir_block3(fs, block, inbuf, 0);
126}
127
128