dirblock.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * dirblock.c --- directory block routines.
  4. *
  5. * Copyright (C) 1995, 1996 Theodore Ts'o.
  6. *
  7. * %Begin-Header%
  8. * This file may be redistributed under the terms of the GNU Public
  9. * License.
  10. * %End-Header%
  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. #include "ext2_fs.h"
  19. #include "ext2fs.h"
  20. errcode_t ext2fs_read_dir_block2(ext2_filsys fs, blk_t block,
  21. void *buf, int flags EXT2FS_ATTR((unused)))
  22. {
  23. errcode_t retval;
  24. char *p, *end;
  25. struct ext2_dir_entry *dirent;
  26. unsigned int name_len, rec_len;
  27. #if BB_BIG_ENDIAN
  28. unsigned int do_swap;
  29. #endif
  30. retval = io_channel_read_blk(fs->io, block, 1, buf);
  31. if (retval)
  32. return retval;
  33. #if BB_BIG_ENDIAN
  34. do_swap = (fs->flags & (EXT2_FLAG_SWAP_BYTES|
  35. EXT2_FLAG_SWAP_BYTES_READ)) != 0;
  36. #endif
  37. p = (char *) buf;
  38. end = (char *) buf + fs->blocksize;
  39. while (p < end-8) {
  40. dirent = (struct ext2_dir_entry *) p;
  41. #if BB_BIG_ENDIAN
  42. if (do_swap) {
  43. dirent->inode = ext2fs_swab32(dirent->inode);
  44. dirent->rec_len = ext2fs_swab16(dirent->rec_len);
  45. dirent->name_len = ext2fs_swab16(dirent->name_len);
  46. }
  47. #endif
  48. name_len = dirent->name_len;
  49. #ifdef WORDS_BIGENDIAN
  50. if (flags & EXT2_DIRBLOCK_V2_STRUCT)
  51. dirent->name_len = ext2fs_swab16(dirent->name_len);
  52. #endif
  53. rec_len = dirent->rec_len;
  54. if ((rec_len < 8) || (rec_len % 4)) {
  55. rec_len = 8;
  56. retval = EXT2_ET_DIR_CORRUPTED;
  57. }
  58. if (((name_len & 0xFF) + 8) > dirent->rec_len)
  59. retval = EXT2_ET_DIR_CORRUPTED;
  60. p += rec_len;
  61. }
  62. return retval;
  63. }
  64. errcode_t ext2fs_read_dir_block(ext2_filsys fs, blk_t block,
  65. void *buf)
  66. {
  67. return ext2fs_read_dir_block2(fs, block, buf, 0);
  68. }
  69. errcode_t ext2fs_write_dir_block2(ext2_filsys fs, blk_t block,
  70. void *inbuf, int flags EXT2FS_ATTR((unused)))
  71. {
  72. #if BB_BIG_ENDIAN
  73. int do_swap = 0;
  74. errcode_t retval;
  75. char *p, *end;
  76. char *buf = 0;
  77. struct ext2_dir_entry *dirent;
  78. if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ||
  79. (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE))
  80. do_swap = 1;
  81. #ifndef WORDS_BIGENDIAN
  82. if (!do_swap)
  83. return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
  84. #endif
  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 ((dirent->rec_len < 8) ||
  94. (dirent->rec_len % 4)) {
  95. ext2fs_free_mem(&buf);
  96. return EXT2_ET_DIR_CORRUPTED;
  97. }
  98. p += dirent->rec_len;
  99. if (do_swap) {
  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. #ifdef WORDS_BIGENDIAN
  105. if (flags & EXT2_DIRBLOCK_V2_STRUCT)
  106. dirent->name_len = ext2fs_swab16(dirent->name_len);
  107. #endif
  108. }
  109. retval = io_channel_write_blk(fs->io, block, 1, buf);
  110. ext2fs_free_mem(&buf);
  111. return retval;
  112. #else
  113. return io_channel_write_blk(fs->io, block, 1, (char *) inbuf);
  114. #endif
  115. }
  116. errcode_t ext2fs_write_dir_block(ext2_filsys fs, blk_t block,
  117. void *inbuf)
  118. {
  119. return ext2fs_write_dir_block2(fs, block, inbuf, 0);
  120. }