inode_io.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * inode_io.c --- This is allows an inode in an ext2 filesystem image
  4. * to be accessed via the I/O manager interface.
  5. *
  6. * Copyright (C) 2002 Theodore Ts'o.
  7. *
  8. * %Begin-Header%
  9. * This file may be redistributed under the terms of the GNU Public
  10. * License.
  11. * %End-Header%
  12. */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #if HAVE_UNISTD_H
  16. #include <unistd.h>
  17. #endif
  18. #if HAVE_ERRNO_H
  19. #include <errno.h>
  20. #endif
  21. #include <time.h>
  22. #include "ext2_fs.h"
  23. #include "ext2fs.h"
  24. /*
  25. * For checking structure magic numbers...
  26. */
  27. #define EXT2_CHECK_MAGIC(struct, code) \
  28. if ((struct)->magic != (code)) return (code)
  29. struct inode_private_data {
  30. int magic;
  31. char name[32];
  32. ext2_file_t file;
  33. ext2_filsys fs;
  34. ext2_ino_t ino;
  35. struct ext2_inode inode;
  36. int flags;
  37. struct inode_private_data *next;
  38. };
  39. #define CHANNEL_HAS_INODE 0x8000
  40. static struct inode_private_data *top_intern;
  41. static int ino_unique = 0;
  42. static errcode_t inode_open(const char *name, int flags, io_channel *channel);
  43. static errcode_t inode_close(io_channel channel);
  44. static errcode_t inode_set_blksize(io_channel channel, int blksize);
  45. static errcode_t inode_read_blk(io_channel channel, unsigned long block,
  46. int count, void *data);
  47. static errcode_t inode_write_blk(io_channel channel, unsigned long block,
  48. int count, const void *data);
  49. static errcode_t inode_flush(io_channel channel);
  50. static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
  51. int size, const void *data);
  52. static struct struct_io_manager struct_inode_manager = {
  53. EXT2_ET_MAGIC_IO_MANAGER,
  54. "Inode I/O Manager",
  55. inode_open,
  56. inode_close,
  57. inode_set_blksize,
  58. inode_read_blk,
  59. inode_write_blk,
  60. inode_flush,
  61. inode_write_byte
  62. };
  63. io_manager inode_io_manager = &struct_inode_manager;
  64. errcode_t ext2fs_inode_io_intern2(ext2_filsys fs, ext2_ino_t ino,
  65. struct ext2_inode *inode,
  66. char **name)
  67. {
  68. struct inode_private_data *data;
  69. errcode_t retval;
  70. if ((retval = ext2fs_get_mem(sizeof(struct inode_private_data),
  71. &data)))
  72. return retval;
  73. data->magic = EXT2_ET_MAGIC_INODE_IO_CHANNEL;
  74. sprintf(data->name, "%u:%d", ino, ino_unique++);
  75. data->file = 0;
  76. data->fs = fs;
  77. data->ino = ino;
  78. data->flags = 0;
  79. if (inode) {
  80. memcpy(&data->inode, inode, sizeof(struct ext2_inode));
  81. data->flags |= CHANNEL_HAS_INODE;
  82. }
  83. data->next = top_intern;
  84. top_intern = data;
  85. *name = data->name;
  86. return 0;
  87. }
  88. errcode_t ext2fs_inode_io_intern(ext2_filsys fs, ext2_ino_t ino,
  89. char **name)
  90. {
  91. return ext2fs_inode_io_intern2(fs, ino, NULL, name);
  92. }
  93. static errcode_t inode_open(const char *name, int flags, io_channel *channel)
  94. {
  95. io_channel io = NULL;
  96. struct inode_private_data *prev, *data = NULL;
  97. errcode_t retval;
  98. int open_flags;
  99. if (name == 0)
  100. return EXT2_ET_BAD_DEVICE_NAME;
  101. for (data = top_intern, prev = NULL; data;
  102. prev = data, data = data->next)
  103. if (strcmp(name, data->name) == 0)
  104. break;
  105. if (!data)
  106. return ENOENT;
  107. if (prev)
  108. prev->next = data->next;
  109. else
  110. top_intern = data->next;
  111. retval = ext2fs_get_mem(sizeof(struct struct_io_channel), &io);
  112. if (retval)
  113. goto cleanup;
  114. memset(io, 0, sizeof(struct struct_io_channel));
  115. io->magic = EXT2_ET_MAGIC_IO_CHANNEL;
  116. io->manager = inode_io_manager;
  117. retval = ext2fs_get_mem(strlen(name)+1, &io->name);
  118. if (retval)
  119. goto cleanup;
  120. strcpy(io->name, name);
  121. io->private_data = data;
  122. io->block_size = 1024;
  123. io->read_error = 0;
  124. io->write_error = 0;
  125. io->refcount = 1;
  126. open_flags = (flags & IO_FLAG_RW) ? EXT2_FILE_WRITE : 0;
  127. retval = ext2fs_file_open2(data->fs, data->ino,
  128. (data->flags & CHANNEL_HAS_INODE) ?
  129. &data->inode : 0, open_flags,
  130. &data->file);
  131. if (retval)
  132. goto cleanup;
  133. *channel = io;
  134. return 0;
  135. cleanup:
  136. if (data) {
  137. ext2fs_free_mem(&data);
  138. }
  139. if (io)
  140. ext2fs_free_mem(&io);
  141. return retval;
  142. }
  143. static errcode_t inode_close(io_channel channel)
  144. {
  145. struct inode_private_data *data;
  146. errcode_t retval = 0;
  147. EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
  148. data = (struct inode_private_data *) channel->private_data;
  149. EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
  150. if (--channel->refcount > 0)
  151. return 0;
  152. retval = ext2fs_file_close(data->file);
  153. ext2fs_free_mem(&channel->private_data);
  154. if (channel->name)
  155. ext2fs_free_mem(&channel->name);
  156. ext2fs_free_mem(&channel);
  157. return retval;
  158. }
  159. static errcode_t inode_set_blksize(io_channel channel, int blksize)
  160. {
  161. struct inode_private_data *data;
  162. EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
  163. data = (struct inode_private_data *) channel->private_data;
  164. EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
  165. channel->block_size = blksize;
  166. return 0;
  167. }
  168. static errcode_t inode_read_blk(io_channel channel, unsigned long block,
  169. int count, void *buf)
  170. {
  171. struct inode_private_data *data;
  172. errcode_t retval;
  173. EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
  174. data = (struct inode_private_data *) channel->private_data;
  175. EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
  176. if ((retval = ext2fs_file_lseek(data->file,
  177. block * channel->block_size,
  178. EXT2_SEEK_SET, 0)))
  179. return retval;
  180. count = (count < 0) ? -count : (count * channel->block_size);
  181. return ext2fs_file_read(data->file, buf, count, 0);
  182. }
  183. static errcode_t inode_write_blk(io_channel channel, unsigned long block,
  184. int count, const void *buf)
  185. {
  186. struct inode_private_data *data;
  187. errcode_t retval;
  188. EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
  189. data = (struct inode_private_data *) channel->private_data;
  190. EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
  191. if ((retval = ext2fs_file_lseek(data->file,
  192. block * channel->block_size,
  193. EXT2_SEEK_SET, 0)))
  194. return retval;
  195. count = (count < 0) ? -count : (count * channel->block_size);
  196. return ext2fs_file_write(data->file, buf, count, 0);
  197. }
  198. static errcode_t inode_write_byte(io_channel channel, unsigned long offset,
  199. int size, const void *buf)
  200. {
  201. struct inode_private_data *data;
  202. errcode_t retval = 0;
  203. EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
  204. data = (struct inode_private_data *) channel->private_data;
  205. EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
  206. if ((retval = ext2fs_file_lseek(data->file, offset,
  207. EXT2_SEEK_SET, 0)))
  208. return retval;
  209. return ext2fs_file_write(data->file, buf, size, 0);
  210. }
  211. /*
  212. * Flush data buffers to disk.
  213. */
  214. static errcode_t inode_flush(io_channel channel)
  215. {
  216. struct inode_private_data *data;
  217. EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
  218. data = (struct inode_private_data *) channel->private_data;
  219. EXT2_CHECK_MAGIC(data, EXT2_ET_MAGIC_INODE_IO_CHANNEL);
  220. return ext2fs_file_flush(data->file);
  221. }