150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o/*
250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o * dirblock.c --- directory block routines.
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1995, 1996 Theodore Ts'o.
521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *
621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header%
7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library
8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2.
921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header%
1050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o */
1150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
1250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <stdio.h>
134cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#if HAVE_UNISTD_H
1450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <unistd.h>
154cbe8af4b0d0c72fb28bb500c1bd8a46b00fdde3Theodore Ts'o#endif
1621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include <string.h>
1750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <time.h>
1850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
19b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h"
2050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include "ext2fs.h"
2150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
22e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_read_dir_block3(ext2_filsys fs, blk64_t block,
23544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				 void *buf, int flags EXT2FS_ATTR((unused)))
2450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
2550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	errcode_t	retval;
2650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char		*p, *end;
2750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct ext2_dir_entry *dirent;
28126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o	unsigned int	name_len, rec_len;
29efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
3050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
31e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = io_channel_read_blk64(fs->io, block, 1, buf);
3250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (retval)
3350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		return retval;
34126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o
35b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o	p = (char *) buf;
3650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	end = (char *) buf + fs->blocksize;
37e446d71838c8fde06e59bd4eb01de031825c6f2bTheodore Ts'o	while (p < end-8) {
38bfcd9a116ff3bcc6d94a616ab1444eb38d0d5434Theodore Ts'o		dirent = (struct ext2_dir_entry *) p;
39126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN
40126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		dirent->inode = ext2fs_swab32(dirent->inode);
41126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		dirent->rec_len = ext2fs_swab16(dirent->rec_len);
42126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		dirent->name_len = ext2fs_swab16(dirent->name_len);
435df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif
44f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o		name_len = dirent->name_len;
45f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o#ifdef WORDS_BIGENDIAN
46f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
47f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o			dirent->name_len = ext2fs_swab16(dirent->name_len);
48f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o#endif
498a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		if ((retval = ext2fs_get_rec_len(fs, dirent, &rec_len)) != 0)
508a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o			return retval;
511cca4d60367c89bcdeb2ee6f1d54ab6f393f289dTheodore Ts'o		if ((rec_len < 8) || (rec_len % 4)) {
521cca4d60367c89bcdeb2ee6f1d54ab6f393f289dTheodore Ts'o			rec_len = 8;
531cca4d60367c89bcdeb2ee6f1d54ab6f393f289dTheodore Ts'o			retval = EXT2_ET_DIR_CORRUPTED;
545dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		} else if (((name_len & 0xFF) + 8) > rec_len)
551cca4d60367c89bcdeb2ee6f1d54ab6f393f289dTheodore Ts'o			retval = EXT2_ET_DIR_CORRUPTED;
561cca4d60367c89bcdeb2ee6f1d54ab6f393f289dTheodore Ts'o		p += rec_len;
5750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
581cca4d60367c89bcdeb2ee6f1d54ab6f393f289dTheodore Ts'o	return retval;
5950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
6050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
61e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 void *buf, int flags EXT2FS_ATTR((unused)))
63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ext2fs_read_dir_block3(fs, block, buf, flags);
65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
67f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'oerrcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
68f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o				 void *buf)
6950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o{
70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ext2fs_read_dir_block3(fs, block, buf, 0);
71f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o}
72f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o
73f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o
74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_write_dir_block3(ext2_filsys fs, blk64_t block,
75544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o				  void *inbuf, int flags EXT2FS_ATTR((unused)))
76f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o{
77126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN
7850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	errcode_t	retval;
79f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o	char		*p, *end;
8050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	char		*buf = 0;
818a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o	unsigned int	rec_len;
8250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	struct ext2_dir_entry *dirent;
8350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
84c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	retval = ext2fs_get_mem(fs->blocksize, &buf);
85f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o	if (retval)
86f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o		return retval;
87f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o	memcpy(buf, inbuf, fs->blocksize);
88f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o	p = buf;
89f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o	end = buf + fs->blocksize;
90f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o	while (p < end) {
91f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o		dirent = (struct ext2_dir_entry *) p;
928a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o		if ((retval = ext2fs_get_rec_len(fs, dirent, &rec_len)) != 0)
938a480350952f6f0fdbce54326b6d847e66368897Theodore Ts'o			return retval;
945dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		if ((rec_len < 8) ||
955dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		    (rec_len % 4)) {
96c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o			ext2fs_free_mem(&buf);
97f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o			return (EXT2_ET_DIR_CORRUPTED);
98f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o		}
995dd77dbe5a0ac6d78c1c6441fae4087be56d9088Theodore Ts'o		p += rec_len;
100126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		dirent->inode = ext2fs_swab32(dirent->inode);
101126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		dirent->rec_len = ext2fs_swab16(dirent->rec_len);
102126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o		dirent->name_len = ext2fs_swab16(dirent->name_len);
103126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o
104f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o		if (flags & EXT2_DIRBLOCK_V2_STRUCT)
105f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o			dirent->name_len = ext2fs_swab16(dirent->name_len);
106f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o	}
107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = io_channel_write_blk64(fs->io, block, 1, buf);
108c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o	ext2fs_free_mem(&buf);
10950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	return retval;
110f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o#else
111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return io_channel_write_blk64(fs->io, block, 1, (char *) inbuf);
112f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o#endif
11350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o}
11450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 void *inbuf, int flags EXT2FS_ATTR((unused)))
117e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ext2fs_write_dir_block3(fs, block, inbuf, flags);
119e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
12050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
121f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'oerrcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
122f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o				 void *inbuf)
123f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o{
124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ext2fs_write_dir_block3(fs, block, inbuf, 0);
125f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o}
126f9190c8a95c6b76eac567d5896b3ed06ed2a3adaTheodore Ts'o
127