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 Public 8 * License. 9 * %End-Header% 10 */ 11 12 #include <stdio.h> 13 #if HAVE_UNISTD_H 14 #include <unistd.h> 15 #endif 16 #include <string.h> 17 #include <time.h> 18 19 #include "ext2_fs.h" 20 #include "ext2fs.h" 21 22 errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block, 23 void *buf, int flags EXT2FS_ATTR((unused))) 24 { 25 errcode_t retval; 26 char *p, *end; 27 struct ext2_dir_entry *dirent; 28 unsigned int name_len, rec_len, do_swap; 29 30 31 retval = io_channel_read_blk(fs->io, block, 1, buf); 32 if (retval) 33 return retval; 34 #ifdef EXT2FS_ENABLE_SWAPFS 35 do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES| 36 EXT2_FLAG_SWAP_BYTES_READ)) != 0; 37 #endif 38 p = (char *) buf; 39 end = (char *) buf + fs->blocksize; 40 while (p < end-8) { 41 dirent = (struct ext2_dir_entry *) p; 42 #ifdef EXT2FS_ENABLE_SWAPFS 43 if (do_swap) { 44 dirent->inode = ext2fs_swab32(dirent->inode); 45 dirent->rec_len = ext2fs_swab16(dirent->rec_len); 46 dirent->name_len = ext2fs_swab16(dirent->name_len); 47 } 48 #endif 49 name_len = dirent->name_len; 50 #ifdef WORDS_BIGENDIAN 51 if (flags & EXT2_DIRBLOCK_V2_STRUCT) 52 dirent->name_len = ext2fs_swab16(dirent->name_len); 53 #endif 54 rec_len = dirent->rec_len; 55 if ((rec_len < 8) || (rec_len % 4)) { 56 rec_len = 8; 57 retval = EXT2_ET_DIR_CORRUPTED; 58 } 59 if (((name_len & 0xFF) + 8) > dirent->rec_len) 60 retval = EXT2_ET_DIR_CORRUPTED; 61 p += rec_len; 62 } 63 return retval; 64 } 65 66 errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block, 67 void *buf) 68 { 69 return ext2fs_read_dir_block2(fs, block, buf, 0); 70 } 71 72 73 errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block, 74 void *inbuf, int flags EXT2FS_ATTR((unused))) 75 { 76 #ifdef EXT2FS_ENABLE_SWAPFS 77 int do_swap = 0; 78 errcode_t retval; 79 char *p, *end; 80 char *buf = 0; 81 struct ext2_dir_entry *dirent; 82 83 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) || 84 (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)) 85 do_swap = 1; 86 87 #ifndef WORDS_BIGENDIAN 88 if (!do_swap) 89 return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); 90 #endif 91 92 retval = ext2fs_get_mem(fs->blocksize, &buf); 93 if (retval) 94 return retval; 95 memcpy(buf, inbuf, fs->blocksize); 96 p = buf; 97 end = buf + fs->blocksize; 98 while (p < end) { 99 dirent = (struct ext2_dir_entry *) p; 100 if ((dirent->rec_len < 8) || 101 (dirent->rec_len % 4)) { 102 ext2fs_free_mem(&buf); 103 return (EXT2_ET_DIR_CORRUPTED); 104 } 105 p += dirent->rec_len; 106 if (do_swap) { 107 dirent->inode = ext2fs_swab32(dirent->inode); 108 dirent->rec_len = ext2fs_swab16(dirent->rec_len); 109 dirent->name_len = ext2fs_swab16(dirent->name_len); 110 } 111 #ifdef WORDS_BIGENDIAN 112 if (flags & EXT2_DIRBLOCK_V2_STRUCT) 113 dirent->name_len = ext2fs_swab16(dirent->name_len); 114 #endif 115 } 116 retval = io_channel_write_blk(fs->io, block, 1, buf); 117 ext2fs_free_mem(&buf); 118 return retval; 119 #else 120 return io_channel_write_blk(fs->io, block, 1, (char *) inbuf); 121 #endif 122 } 123 124 125 errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block, 126 void *inbuf) 127 { 128 return ext2fs_write_dir_block2(fs, block, inbuf, 0); 129 } 130 131