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