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