reiserfs.c 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. /* reiserfs.c - ReiserFS versions up to 3.6 */
  2. /*
  3. * GRUB -- GRand Unified Bootloader
  4. * Copyright (C) 2003,2004,2005,2008 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /*
  20. TODO:
  21. implement journal handling (ram replay)
  22. test tail packing & direct files
  23. validate partition label position
  24. */
  25. #if 0
  26. # define GRUB_REISERFS_DEBUG
  27. # define GRUB_REISERFS_JOURNALING
  28. # define GRUB_HEXDUMP
  29. #endif
  30. #include <grub/err.h>
  31. #include <grub/file.h>
  32. #include <grub/mm.h>
  33. #include <grub/misc.h>
  34. #include <grub/disk.h>
  35. #include <grub/dl.h>
  36. #include <grub/types.h>
  37. #include <grub/fshelp.h>
  38. #include <grub/i18n.h>
  39. #include <grub/lockdown.h>
  40. GRUB_MOD_LICENSE ("GPLv3+");
  41. #define MIN(a, b) \
  42. ({ typeof (a) _a = (a); \
  43. typeof (b) _b = (b); \
  44. _a < _b ? _a : _b; })
  45. #define MAX(a, b) \
  46. ({ typeof (a) _a = (a); \
  47. typeof (b) _b = (b); \
  48. _a > _b ? _a : _b; })
  49. #define REISERFS_SUPER_BLOCK_OFFSET 0x10000
  50. #define REISERFS_MAGIC_LEN 12
  51. #define REISERFS_MAGIC_STRING "ReIsEr"
  52. #define REISERFS_MAGIC_DESC_BLOCK "ReIsErLB"
  53. /* If the 3rd bit of an item state is set, then it's visible. */
  54. #define GRUB_REISERFS_VISIBLE_MASK ((grub_uint16_t) 0x04)
  55. #define S_IFLNK 0xA000
  56. static grub_dl_t my_mod;
  57. #define assert(boolean) real_assert (boolean, GRUB_FILE, __LINE__)
  58. static inline void
  59. real_assert (int boolean, const char *file, const int line)
  60. {
  61. if (! boolean)
  62. grub_printf ("Assertion failed at %s:%d\n", file, line);
  63. }
  64. enum grub_reiserfs_item_type
  65. {
  66. GRUB_REISERFS_STAT,
  67. GRUB_REISERFS_DIRECTORY,
  68. GRUB_REISERFS_DIRECT,
  69. GRUB_REISERFS_INDIRECT,
  70. /* Matches both _DIRECT and _INDIRECT when searching. */
  71. GRUB_REISERFS_ANY,
  72. GRUB_REISERFS_UNKNOWN
  73. };
  74. struct grub_reiserfs_superblock
  75. {
  76. grub_uint32_t block_count;
  77. grub_uint32_t block_free_count;
  78. grub_uint32_t root_block;
  79. grub_uint32_t journal_block;
  80. grub_uint32_t journal_device;
  81. grub_uint32_t journal_original_size;
  82. grub_uint32_t journal_max_transaction_size;
  83. grub_uint32_t journal_block_count;
  84. grub_uint32_t journal_max_batch;
  85. grub_uint32_t journal_max_commit_age;
  86. grub_uint32_t journal_max_transaction_age;
  87. grub_uint16_t block_size;
  88. grub_uint16_t oid_max_size;
  89. grub_uint16_t oid_current_size;
  90. grub_uint16_t state;
  91. grub_uint8_t magic_string[REISERFS_MAGIC_LEN];
  92. grub_uint32_t function_hash_code;
  93. grub_uint16_t tree_height;
  94. grub_uint16_t bitmap_number;
  95. grub_uint16_t version;
  96. grub_uint16_t reserved;
  97. grub_uint32_t inode_generation;
  98. grub_uint8_t unused[4];
  99. grub_uint16_t uuid[8];
  100. char label[16];
  101. } GRUB_PACKED;
  102. struct grub_reiserfs_journal_header
  103. {
  104. grub_uint32_t last_flush_uid;
  105. grub_uint32_t unflushed_offset;
  106. grub_uint32_t mount_id;
  107. } GRUB_PACKED;
  108. struct grub_reiserfs_description_block
  109. {
  110. grub_uint32_t id;
  111. grub_uint32_t len;
  112. grub_uint32_t mount_id;
  113. grub_uint32_t real_blocks[0];
  114. } GRUB_PACKED;
  115. struct grub_reiserfs_commit_block
  116. {
  117. grub_uint32_t id;
  118. grub_uint32_t len;
  119. grub_uint32_t real_blocks[0];
  120. } GRUB_PACKED;
  121. struct grub_reiserfs_stat_item_v1
  122. {
  123. grub_uint16_t mode;
  124. grub_uint16_t hardlink_count;
  125. grub_uint16_t uid;
  126. grub_uint16_t gid;
  127. grub_uint32_t size;
  128. grub_uint32_t atime;
  129. grub_uint32_t mtime;
  130. grub_uint32_t ctime;
  131. grub_uint32_t rdev;
  132. grub_uint32_t first_direct_byte;
  133. } GRUB_PACKED;
  134. struct grub_reiserfs_stat_item_v2
  135. {
  136. grub_uint16_t mode;
  137. grub_uint16_t reserved;
  138. grub_uint32_t hardlink_count;
  139. grub_uint64_t size;
  140. grub_uint32_t uid;
  141. grub_uint32_t gid;
  142. grub_uint32_t atime;
  143. grub_uint32_t mtime;
  144. grub_uint32_t ctime;
  145. grub_uint32_t blocks;
  146. grub_uint32_t first_direct_byte;
  147. } GRUB_PACKED;
  148. struct grub_reiserfs_key
  149. {
  150. grub_uint32_t directory_id;
  151. grub_uint32_t object_id;
  152. union
  153. {
  154. struct
  155. {
  156. grub_uint32_t offset;
  157. grub_uint32_t type;
  158. } GRUB_PACKED v1;
  159. struct
  160. {
  161. grub_uint64_t offset_type;
  162. } GRUB_PACKED v2;
  163. } u;
  164. } GRUB_PACKED;
  165. struct grub_reiserfs_item_header
  166. {
  167. struct grub_reiserfs_key key;
  168. union
  169. {
  170. grub_uint16_t free_space;
  171. grub_uint16_t entry_count;
  172. } GRUB_PACKED u;
  173. grub_uint16_t item_size;
  174. grub_uint16_t item_location;
  175. grub_uint16_t version;
  176. } GRUB_PACKED;
  177. struct grub_reiserfs_block_header
  178. {
  179. grub_uint16_t level;
  180. grub_uint16_t item_count;
  181. grub_uint16_t free_space;
  182. grub_uint16_t reserved;
  183. struct grub_reiserfs_key block_right_delimiting_key;
  184. } GRUB_PACKED;
  185. struct grub_reiserfs_disk_child
  186. {
  187. grub_uint32_t block_number;
  188. grub_uint16_t size;
  189. grub_uint16_t reserved;
  190. } GRUB_PACKED;
  191. struct grub_reiserfs_directory_header
  192. {
  193. grub_uint32_t offset;
  194. grub_uint32_t directory_id;
  195. grub_uint32_t object_id;
  196. grub_uint16_t location;
  197. grub_uint16_t state;
  198. } GRUB_PACKED;
  199. struct grub_fshelp_node
  200. {
  201. struct grub_reiserfs_data *data;
  202. grub_uint32_t block_number; /* 0 if node is not found. */
  203. grub_uint16_t block_position;
  204. grub_uint64_t next_offset;
  205. grub_int32_t mtime;
  206. grub_off_t size;
  207. enum grub_reiserfs_item_type type; /* To know how to read the header. */
  208. struct grub_reiserfs_item_header header;
  209. };
  210. /* Returned when opening a file. */
  211. struct grub_reiserfs_data
  212. {
  213. struct grub_reiserfs_superblock superblock;
  214. grub_disk_t disk;
  215. };
  216. static grub_ssize_t
  217. grub_reiserfs_read_real (struct grub_fshelp_node *node,
  218. grub_off_t off, char *buf, grub_size_t len,
  219. grub_disk_read_hook_t read_hook,
  220. void *read_hook_data);
  221. /* Internal-only functions. Not to be used outside of this file. */
  222. /* Return the type of given v2 key. */
  223. static enum grub_reiserfs_item_type
  224. grub_reiserfs_get_key_v2_type (const struct grub_reiserfs_key *key)
  225. {
  226. switch (grub_le_to_cpu64 (key->u.v2.offset_type) >> 60)
  227. {
  228. case 0:
  229. return GRUB_REISERFS_STAT;
  230. case 15:
  231. return GRUB_REISERFS_ANY;
  232. case 3:
  233. return GRUB_REISERFS_DIRECTORY;
  234. case 2:
  235. return GRUB_REISERFS_DIRECT;
  236. case 1:
  237. return GRUB_REISERFS_INDIRECT;
  238. }
  239. return GRUB_REISERFS_UNKNOWN;
  240. }
  241. /* Return the type of given v1 key. */
  242. static enum grub_reiserfs_item_type
  243. grub_reiserfs_get_key_v1_type (const struct grub_reiserfs_key *key)
  244. {
  245. switch (grub_le_to_cpu32 (key->u.v1.type))
  246. {
  247. case 0:
  248. return GRUB_REISERFS_STAT;
  249. case 555:
  250. return GRUB_REISERFS_ANY;
  251. case 500:
  252. return GRUB_REISERFS_DIRECTORY;
  253. case 0x20000000:
  254. case 0xFFFFFFFF:
  255. return GRUB_REISERFS_DIRECT;
  256. case 0x10000000:
  257. case 0xFFFFFFFE:
  258. return GRUB_REISERFS_INDIRECT;
  259. }
  260. return GRUB_REISERFS_UNKNOWN;
  261. }
  262. /* Return 1 if the given key is version 1 key, 2 otherwise. */
  263. static int
  264. grub_reiserfs_get_key_version (const struct grub_reiserfs_key *key)
  265. {
  266. return grub_reiserfs_get_key_v1_type (key) == GRUB_REISERFS_UNKNOWN ? 2 : 1;
  267. }
  268. #ifdef GRUB_HEXDUMP
  269. static void
  270. grub_hexdump (char *buffer, grub_size_t len)
  271. {
  272. grub_size_t a;
  273. for (a = 0; a < len; a++)
  274. {
  275. if (! (a & 0x0F))
  276. grub_printf ("\n%08x ", a);
  277. grub_printf ("%02x ",
  278. ((unsigned int) ((unsigned char *) buffer)[a]) & 0xFF);
  279. }
  280. grub_printf ("\n");
  281. }
  282. #endif
  283. #ifdef GRUB_REISERFS_DEBUG
  284. static grub_uint64_t
  285. grub_reiserfs_get_key_offset (const struct grub_reiserfs_key *key);
  286. static enum grub_reiserfs_item_type
  287. grub_reiserfs_get_key_type (const struct grub_reiserfs_key *key);
  288. static void
  289. grub_reiserfs_print_key (const struct grub_reiserfs_key *key)
  290. {
  291. unsigned int a;
  292. char *reiserfs_type_strings[] = {
  293. "stat ",
  294. "directory",
  295. "direct ",
  296. "indirect ",
  297. "any ",
  298. "unknown "
  299. };
  300. for (a = 0; a < sizeof (struct grub_reiserfs_key); a++)
  301. grub_printf ("%02x ", ((unsigned int) ((unsigned char *) key)[a]) & 0xFF);
  302. grub_printf ("parent id = 0x%08x, self id = 0x%08x, type = %s, offset = ",
  303. grub_le_to_cpu32 (key->directory_id),
  304. grub_le_to_cpu32 (key->object_id),
  305. reiserfs_type_strings [grub_reiserfs_get_key_type (key)]);
  306. if (grub_reiserfs_get_key_version (key) == 1)
  307. grub_printf("%08x", (unsigned int) grub_reiserfs_get_key_offset (key));
  308. else
  309. grub_printf("0x%07x%08x",
  310. (unsigned) (grub_reiserfs_get_key_offset (key) >> 32),
  311. (unsigned) (grub_reiserfs_get_key_offset (key) & 0xFFFFFFFF));
  312. grub_printf ("\n");
  313. }
  314. #endif
  315. /* Return the offset of given key. */
  316. static grub_uint64_t
  317. grub_reiserfs_get_key_offset (const struct grub_reiserfs_key *key)
  318. {
  319. if (grub_reiserfs_get_key_version (key) == 1)
  320. return grub_le_to_cpu32 (key->u.v1.offset);
  321. else
  322. return grub_le_to_cpu64 (key->u.v2.offset_type) & (~0ULL >> 4);
  323. }
  324. /* Set the offset of given key. */
  325. static void
  326. grub_reiserfs_set_key_offset (struct grub_reiserfs_key *key,
  327. grub_uint64_t value)
  328. {
  329. if (grub_reiserfs_get_key_version (key) == 1)
  330. key->u.v1.offset = grub_cpu_to_le32 (value);
  331. else
  332. key->u.v2.offset_type \
  333. = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (15ULL << 60))
  334. | grub_cpu_to_le64 (value & (~0ULL >> 4)));
  335. }
  336. /* Return the type of given key. */
  337. static enum grub_reiserfs_item_type
  338. grub_reiserfs_get_key_type (const struct grub_reiserfs_key *key)
  339. {
  340. if (grub_reiserfs_get_key_version (key) == 1)
  341. return grub_reiserfs_get_key_v1_type (key);
  342. else
  343. return grub_reiserfs_get_key_v2_type (key);
  344. }
  345. /* Set the type of given key, with given version number. */
  346. static void
  347. grub_reiserfs_set_key_type (struct grub_reiserfs_key *key,
  348. enum grub_reiserfs_item_type grub_type,
  349. int version)
  350. {
  351. grub_uint32_t type;
  352. switch (grub_type)
  353. {
  354. case GRUB_REISERFS_STAT:
  355. type = 0;
  356. break;
  357. case GRUB_REISERFS_ANY:
  358. type = (version == 1) ? 555 : 15;
  359. break;
  360. case GRUB_REISERFS_DIRECTORY:
  361. type = (version == 1) ? 500 : 3;
  362. break;
  363. case GRUB_REISERFS_DIRECT:
  364. type = (version == 1) ? 0xFFFFFFFF : 2;
  365. break;
  366. case GRUB_REISERFS_INDIRECT:
  367. type = (version == 1) ? 0xFFFFFFFE : 1;
  368. break;
  369. default:
  370. return;
  371. }
  372. if (version == 1)
  373. key->u.v1.type = grub_cpu_to_le32 (type);
  374. else
  375. key->u.v2.offset_type
  376. = ((key->u.v2.offset_type & grub_cpu_to_le64_compile_time (~0ULL >> 4))
  377. | grub_cpu_to_le64 ((grub_uint64_t) type << 60));
  378. assert (grub_reiserfs_get_key_type (key) == grub_type);
  379. }
  380. /* -1 if key 1 if lower than key 2.
  381. 0 if key 1 is equal to key 2.
  382. 1 if key 1 is higher than key 2. */
  383. static int
  384. grub_reiserfs_compare_keys (const struct grub_reiserfs_key *key1,
  385. const struct grub_reiserfs_key *key2)
  386. {
  387. grub_uint64_t offset1, offset2;
  388. enum grub_reiserfs_item_type type1, type2;
  389. grub_uint32_t id1, id2;
  390. if (! key1 || ! key2)
  391. return -2;
  392. id1 = grub_le_to_cpu32 (key1->directory_id);
  393. id2 = grub_le_to_cpu32 (key2->directory_id);
  394. if (id1 < id2)
  395. return -1;
  396. if (id1 > id2)
  397. return 1;
  398. id1 = grub_le_to_cpu32 (key1->object_id);
  399. id2 = grub_le_to_cpu32 (key2->object_id);
  400. if (id1 < id2)
  401. return -1;
  402. if (id1 > id2)
  403. return 1;
  404. offset1 = grub_reiserfs_get_key_offset (key1);
  405. offset2 = grub_reiserfs_get_key_offset (key2);
  406. if (offset1 < offset2)
  407. return -1;
  408. if (offset1 > offset2)
  409. return 1;
  410. type1 = grub_reiserfs_get_key_type (key1);
  411. type2 = grub_reiserfs_get_key_type (key2);
  412. if ((type1 == GRUB_REISERFS_ANY
  413. && (type2 == GRUB_REISERFS_DIRECT
  414. || type2 == GRUB_REISERFS_INDIRECT))
  415. || (type2 == GRUB_REISERFS_ANY
  416. && (type1 == GRUB_REISERFS_DIRECT
  417. || type1 == GRUB_REISERFS_INDIRECT)))
  418. return 0;
  419. if (type1 < type2)
  420. return -1;
  421. if (type1 > type2)
  422. return 1;
  423. return 0;
  424. }
  425. /* Find the item identified by KEY in mounted filesystem DATA, and fill ITEM
  426. accordingly to what was found. */
  427. static grub_err_t
  428. grub_reiserfs_get_item (struct grub_reiserfs_data *data,
  429. const struct grub_reiserfs_key *key,
  430. struct grub_fshelp_node *item, int exact)
  431. {
  432. grub_uint32_t block_number;
  433. struct grub_reiserfs_block_header *block_header = 0;
  434. struct grub_reiserfs_key *block_key = 0;
  435. grub_uint16_t block_size, item_count, current_level;
  436. grub_uint16_t i;
  437. grub_uint16_t previous_level = ~0;
  438. struct grub_reiserfs_item_header *item_headers = 0;
  439. #if 0
  440. if (! data)
  441. {
  442. grub_error (GRUB_ERR_BAD_FS, "data is NULL");
  443. goto fail;
  444. }
  445. if (! key)
  446. {
  447. grub_error (GRUB_ERR_BAD_FS, "key is NULL");
  448. goto fail;
  449. }
  450. if (! item)
  451. {
  452. grub_error (GRUB_ERR_BAD_FS, "item is NULL");
  453. goto fail;
  454. }
  455. #endif
  456. block_size = grub_le_to_cpu16 (data->superblock.block_size);
  457. block_number = grub_le_to_cpu32 (data->superblock.root_block);
  458. #ifdef GRUB_REISERFS_DEBUG
  459. grub_printf("Searching for ");
  460. grub_reiserfs_print_key (key);
  461. #endif
  462. block_header = grub_malloc (block_size);
  463. if (! block_header)
  464. goto fail;
  465. item->next_offset = 0;
  466. do
  467. {
  468. grub_disk_read (data->disk,
  469. block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
  470. (((grub_off_t) block_number * block_size)
  471. & (GRUB_DISK_SECTOR_SIZE - 1)),
  472. block_size, block_header);
  473. if (grub_errno)
  474. goto fail;
  475. current_level = grub_le_to_cpu16 (block_header->level);
  476. grub_dprintf ("reiserfs_tree", " at level %d\n", current_level);
  477. if (current_level >= previous_level)
  478. {
  479. grub_dprintf ("reiserfs_tree", "level loop detected, aborting\n");
  480. grub_error (GRUB_ERR_BAD_FS, "level loop");
  481. goto fail;
  482. }
  483. previous_level = current_level;
  484. item_count = grub_le_to_cpu16 (block_header->item_count);
  485. grub_dprintf ("reiserfs_tree", " number of contained items : %d\n",
  486. item_count);
  487. if (current_level > 1)
  488. {
  489. /* Internal node. Navigate to the child that should contain
  490. the searched key. */
  491. struct grub_reiserfs_key *keys
  492. = (struct grub_reiserfs_key *) (block_header + 1);
  493. struct grub_reiserfs_disk_child *children
  494. = ((struct grub_reiserfs_disk_child *)
  495. (keys + item_count));
  496. for (i = 0;
  497. i < item_count
  498. && grub_reiserfs_compare_keys (key, &(keys[i])) >= 0;
  499. i++)
  500. {
  501. #ifdef GRUB_REISERFS_DEBUG
  502. grub_printf("i %03d/%03d ", i + 1, item_count + 1);
  503. grub_reiserfs_print_key (&(keys[i]));
  504. #endif
  505. }
  506. block_number = grub_le_to_cpu32 (children[i].block_number);
  507. if ((i < item_count) && (key->directory_id == keys[i].directory_id)
  508. && (key->object_id == keys[i].object_id))
  509. item->next_offset = grub_reiserfs_get_key_offset(&(keys[i]));
  510. #ifdef GRUB_REISERFS_DEBUG
  511. if (i == item_count
  512. || grub_reiserfs_compare_keys (key, &(keys[i])) == 0)
  513. grub_printf(">");
  514. else
  515. grub_printf("<");
  516. if (i < item_count)
  517. {
  518. grub_printf (" %03d/%03d ", i + 1, item_count + 1);
  519. grub_reiserfs_print_key (&(keys[i]));
  520. if (i + 1 < item_count)
  521. {
  522. grub_printf ("+ %03d/%03d ", i + 2, item_count);
  523. grub_reiserfs_print_key (&(keys[i + 1]));
  524. }
  525. }
  526. else
  527. grub_printf ("Accessing rightmost child at block %d.\n",
  528. block_number);
  529. #endif
  530. }
  531. else
  532. {
  533. /* Leaf node. Check that the key is actually present. */
  534. item_headers
  535. = (struct grub_reiserfs_item_header *) (block_header + 1);
  536. for (i = 0;
  537. i < item_count;
  538. i++)
  539. {
  540. int val;
  541. val = grub_reiserfs_compare_keys (key, &(item_headers[i].key));
  542. if (val == 0)
  543. {
  544. block_key = &(item_headers[i].key);
  545. break;
  546. }
  547. if (val < 0 && exact)
  548. break;
  549. if (val < 0)
  550. {
  551. if (i == 0)
  552. {
  553. grub_error (GRUB_ERR_READ_ERROR, "unexpected btree node");
  554. goto fail;
  555. }
  556. i--;
  557. block_key = &(item_headers[i].key);
  558. break;
  559. }
  560. }
  561. if (!exact && i == item_count)
  562. {
  563. if (i == 0)
  564. {
  565. grub_error (GRUB_ERR_READ_ERROR, "unexpected btree node");
  566. goto fail;
  567. }
  568. i--;
  569. block_key = &(item_headers[i].key);
  570. }
  571. }
  572. }
  573. while (current_level > 1);
  574. item->data = data;
  575. if (!block_key)
  576. {
  577. item->block_number = 0;
  578. item->block_position = 0;
  579. item->type = GRUB_REISERFS_UNKNOWN;
  580. #ifdef GRUB_REISERFS_DEBUG
  581. grub_printf("Not found.\n");
  582. #endif
  583. }
  584. else
  585. {
  586. item->block_number = block_number;
  587. item->block_position = i;
  588. item->type = grub_reiserfs_get_key_type (block_key);
  589. grub_memcpy (&(item->header), &(item_headers[i]),
  590. sizeof (struct grub_reiserfs_item_header));
  591. #ifdef GRUB_REISERFS_DEBUG
  592. grub_printf ("F %03d/%03d ", i + 1, item_count);
  593. grub_reiserfs_print_key (block_key);
  594. #endif
  595. }
  596. assert (grub_errno == GRUB_ERR_NONE);
  597. grub_free (block_header);
  598. return GRUB_ERR_NONE;
  599. fail:
  600. assert (grub_errno != GRUB_ERR_NONE);
  601. grub_free (block_header);
  602. assert (grub_errno != GRUB_ERR_NONE);
  603. return grub_errno;
  604. }
  605. /* Return the path of the file which is pointed at by symlink NODE. */
  606. static char *
  607. grub_reiserfs_read_symlink (grub_fshelp_node_t node)
  608. {
  609. char *symlink_buffer = 0;
  610. grub_size_t len = node->size;
  611. grub_ssize_t ret;
  612. symlink_buffer = grub_malloc (len + 1);
  613. if (! symlink_buffer)
  614. return 0;
  615. ret = grub_reiserfs_read_real (node, 0, symlink_buffer, len, 0, 0);
  616. if (ret < 0)
  617. {
  618. grub_free (symlink_buffer);
  619. return 0;
  620. }
  621. symlink_buffer[ret] = 0;
  622. return symlink_buffer;
  623. }
  624. /* Fill the mounted filesystem structure and return it. */
  625. static struct grub_reiserfs_data *
  626. grub_reiserfs_mount (grub_disk_t disk)
  627. {
  628. struct grub_reiserfs_data *data = 0;
  629. data = grub_malloc (sizeof (*data));
  630. if (! data)
  631. goto fail;
  632. grub_disk_read (disk, REISERFS_SUPER_BLOCK_OFFSET / GRUB_DISK_SECTOR_SIZE,
  633. 0, sizeof (data->superblock), &(data->superblock));
  634. if (grub_errno)
  635. goto fail;
  636. if (grub_memcmp (data->superblock.magic_string,
  637. REISERFS_MAGIC_STRING, sizeof (REISERFS_MAGIC_STRING) - 1))
  638. {
  639. grub_error (GRUB_ERR_BAD_FS, "not a ReiserFS filesystem");
  640. goto fail;
  641. }
  642. data->disk = disk;
  643. return data;
  644. fail:
  645. /* Disk is too small to contain a ReiserFS. */
  646. if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
  647. grub_error (GRUB_ERR_BAD_FS, "not a ReiserFS filesystem");
  648. grub_free (data);
  649. return 0;
  650. }
  651. /* Call HOOK for each file in directory ITEM. */
  652. static int
  653. grub_reiserfs_iterate_dir (grub_fshelp_node_t item,
  654. grub_fshelp_iterate_dir_hook_t hook,
  655. void *hook_data)
  656. {
  657. struct grub_reiserfs_data *data = item->data;
  658. struct grub_reiserfs_block_header *block_header = 0;
  659. grub_uint16_t block_size, block_position;
  660. grub_uint32_t block_number;
  661. grub_uint64_t next_offset = item->next_offset;
  662. int ret = 0;
  663. if (item->type != GRUB_REISERFS_DIRECTORY)
  664. {
  665. grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
  666. goto fail;
  667. }
  668. block_size = grub_le_to_cpu16 (data->superblock.block_size);
  669. block_header = grub_malloc (block_size + 1);
  670. if (! block_header)
  671. goto fail;
  672. block_number = item->block_number;
  673. block_position = item->block_position;
  674. grub_dprintf ("reiserfs", "Iterating directory...\n");
  675. do
  676. {
  677. struct grub_reiserfs_directory_header *directory_headers;
  678. struct grub_fshelp_node directory_item;
  679. grub_uint16_t entry_count, entry_number;
  680. struct grub_reiserfs_item_header *item_headers;
  681. grub_disk_read (data->disk,
  682. block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
  683. (((grub_off_t) block_number * block_size)
  684. & (GRUB_DISK_SECTOR_SIZE - 1)),
  685. block_size, (char *) block_header);
  686. if (grub_errno)
  687. goto fail;
  688. ((char *) block_header)[block_size] = 0;
  689. #if 0
  690. if (grub_le_to_cpu16 (block_header->level) != 1)
  691. {
  692. grub_error (GRUB_ERR_BAD_FS,
  693. "reiserfs: block %d is not a leaf block",
  694. block_number);
  695. goto fail;
  696. }
  697. #endif
  698. item_headers = (struct grub_reiserfs_item_header *) (block_header + 1);
  699. directory_headers
  700. = ((struct grub_reiserfs_directory_header *)
  701. ((char *) block_header
  702. + grub_le_to_cpu16 (item_headers[block_position].item_location)));
  703. entry_count
  704. = grub_le_to_cpu16 (item_headers[block_position].u.entry_count);
  705. for (entry_number = 0; entry_number < entry_count; entry_number++)
  706. {
  707. struct grub_reiserfs_directory_header *directory_header
  708. = &directory_headers[entry_number];
  709. grub_uint16_t entry_state
  710. = grub_le_to_cpu16 (directory_header->state);
  711. grub_fshelp_node_t entry_item;
  712. struct grub_reiserfs_key entry_key;
  713. enum grub_fshelp_filetype entry_type;
  714. char *entry_name;
  715. char *entry_name_end = 0;
  716. char c;
  717. if (!(entry_state & GRUB_REISERFS_VISIBLE_MASK))
  718. continue;
  719. entry_name = (((char *) directory_headers)
  720. + grub_le_to_cpu16 (directory_header->location));
  721. if (entry_number == 0)
  722. {
  723. entry_name_end = (char *) block_header
  724. + grub_le_to_cpu16 (item_headers[block_position].item_location)
  725. + grub_le_to_cpu16 (item_headers[block_position].item_size);
  726. }
  727. else
  728. {
  729. entry_name_end = (((char *) directory_headers)
  730. + grub_le_to_cpu16 (directory_headers[entry_number - 1].location));
  731. }
  732. if (entry_name_end < entry_name || entry_name_end > (char *) block_header + block_size)
  733. {
  734. entry_name_end = (char *) block_header + block_size;
  735. }
  736. entry_key.directory_id = directory_header->directory_id;
  737. entry_key.object_id = directory_header->object_id;
  738. entry_key.u.v2.offset_type = 0;
  739. grub_reiserfs_set_key_type (&entry_key, GRUB_REISERFS_DIRECTORY,
  740. 2);
  741. grub_reiserfs_set_key_offset (&entry_key, 1);
  742. entry_item = grub_malloc (sizeof (*entry_item));
  743. if (! entry_item)
  744. goto fail;
  745. if (grub_reiserfs_get_item (data, &entry_key, entry_item, 1)
  746. != GRUB_ERR_NONE)
  747. {
  748. grub_free (entry_item);
  749. goto fail;
  750. }
  751. if (entry_item->type == GRUB_REISERFS_DIRECTORY)
  752. entry_type = GRUB_FSHELP_DIR;
  753. else
  754. {
  755. grub_uint32_t entry_block_number;
  756. /* Order is very important here.
  757. First set the offset to 0 using current key version.
  758. Then change the key type, which affects key version
  759. detection. */
  760. grub_reiserfs_set_key_offset (&entry_key, 0);
  761. grub_reiserfs_set_key_type (&entry_key, GRUB_REISERFS_STAT,
  762. 2);
  763. if (grub_reiserfs_get_item (data, &entry_key, entry_item, 1)
  764. != GRUB_ERR_NONE)
  765. {
  766. grub_free (entry_item);
  767. goto fail;
  768. }
  769. if (entry_item->block_number != 0)
  770. {
  771. grub_uint16_t entry_version;
  772. entry_version
  773. = grub_le_to_cpu16 (entry_item->header.version);
  774. entry_block_number = entry_item->block_number;
  775. #if 0
  776. grub_dprintf ("reiserfs",
  777. "version %04x block %08x (%08x) position %08x\n",
  778. entry_version, entry_block_number,
  779. ((grub_disk_addr_t) entry_block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
  780. grub_le_to_cpu16 (entry_item->header.item_location));
  781. #endif
  782. if (entry_version == 0) /* Version 1 stat item. */
  783. {
  784. struct grub_reiserfs_stat_item_v1 entry_v1_stat;
  785. grub_disk_read (data->disk,
  786. entry_block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
  787. grub_le_to_cpu16 (entry_item->header.item_location),
  788. sizeof (entry_v1_stat),
  789. (char *) &entry_v1_stat);
  790. if (grub_errno)
  791. goto fail;
  792. #if 0
  793. grub_dprintf ("reiserfs",
  794. "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
  795. grub_le_to_cpu16 (entry_v1_stat.mode),
  796. grub_le_to_cpu16 (entry_v1_stat.hardlink_count),
  797. grub_le_to_cpu16 (entry_v1_stat.uid),
  798. grub_le_to_cpu16 (entry_v1_stat.gid),
  799. grub_le_to_cpu32 (entry_v1_stat.size),
  800. grub_le_to_cpu32 (entry_v1_stat.atime),
  801. grub_le_to_cpu32 (entry_v1_stat.mtime),
  802. grub_le_to_cpu32 (entry_v1_stat.ctime),
  803. grub_le_to_cpu32 (entry_v1_stat.rdev),
  804. grub_le_to_cpu32 (entry_v1_stat.first_direct_byte));
  805. grub_dprintf ("reiserfs",
  806. "%04x %04x %04x %04x %08x %08x | %08x %08x %08x %08x\n",
  807. entry_v1_stat.mode,
  808. entry_v1_stat.hardlink_count,
  809. entry_v1_stat.uid,
  810. entry_v1_stat.gid,
  811. entry_v1_stat.size,
  812. entry_v1_stat.atime,
  813. entry_v1_stat.mtime,
  814. entry_v1_stat.ctime,
  815. entry_v1_stat.rdev,
  816. entry_v1_stat.first_direct_byte);
  817. #endif
  818. entry_item->mtime = grub_le_to_cpu32 (entry_v1_stat.mtime);
  819. if ((grub_le_to_cpu16 (entry_v1_stat.mode) & S_IFLNK)
  820. == S_IFLNK)
  821. entry_type = GRUB_FSHELP_SYMLINK;
  822. else
  823. entry_type = GRUB_FSHELP_REG;
  824. entry_item->size = (grub_off_t) grub_le_to_cpu32 (entry_v1_stat.size);
  825. }
  826. else
  827. {
  828. struct grub_reiserfs_stat_item_v2 entry_v2_stat;
  829. grub_disk_read (data->disk,
  830. entry_block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
  831. grub_le_to_cpu16 (entry_item->header.item_location),
  832. sizeof (entry_v2_stat),
  833. (char *) &entry_v2_stat);
  834. if (grub_errno)
  835. goto fail;
  836. #if 0
  837. grub_dprintf ("reiserfs",
  838. "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
  839. grub_le_to_cpu16 (entry_v2_stat.mode),
  840. grub_le_to_cpu16 (entry_v2_stat.reserved),
  841. grub_le_to_cpu32 (entry_v2_stat.hardlink_count),
  842. (unsigned int) (grub_le_to_cpu64 (entry_v2_stat.size) >> 32),
  843. (unsigned int) (grub_le_to_cpu64 (entry_v2_stat.size) && 0xFFFFFFFF),
  844. grub_le_to_cpu32 (entry_v2_stat.uid),
  845. grub_le_to_cpu32 (entry_v2_stat.gid),
  846. grub_le_to_cpu32 (entry_v2_stat.atime),
  847. grub_le_to_cpu32 (entry_v2_stat.mtime),
  848. grub_le_to_cpu32 (entry_v2_stat.ctime),
  849. grub_le_to_cpu32 (entry_v2_stat.blocks),
  850. grub_le_to_cpu32 (entry_v2_stat.first_direct_byte));
  851. grub_dprintf ("reiserfs",
  852. "%04x %04x %08x %08x%08x | %08x %08x %08x %08x | %08x %08x %08x\n",
  853. entry_v2_stat.mode,
  854. entry_v2_stat.reserved,
  855. entry_v2_stat.hardlink_count,
  856. (unsigned int) (entry_v2_stat.size >> 32),
  857. (unsigned int) (entry_v2_stat.size && 0xFFFFFFFF),
  858. entry_v2_stat.uid,
  859. entry_v2_stat.gid,
  860. entry_v2_stat.atime,
  861. entry_v2_stat.mtime,
  862. entry_v2_stat.ctime,
  863. entry_v2_stat.blocks,
  864. entry_v2_stat.first_direct_byte);
  865. #endif
  866. entry_item->mtime = grub_le_to_cpu32 (entry_v2_stat.mtime);
  867. entry_item->size = (grub_off_t) grub_le_to_cpu64 (entry_v2_stat.size);
  868. if ((grub_le_to_cpu16 (entry_v2_stat.mode) & S_IFLNK)
  869. == S_IFLNK)
  870. entry_type = GRUB_FSHELP_SYMLINK;
  871. else
  872. entry_type = GRUB_FSHELP_REG;
  873. }
  874. }
  875. else
  876. {
  877. /* Pseudo file ".." never has stat block. */
  878. if (entry_name_end == entry_name + 2 && grub_memcmp (entry_name, "..", 2) != 0)
  879. grub_dprintf ("reiserfs",
  880. "Warning : %s has no stat block !\n",
  881. entry_name);
  882. grub_free (entry_item);
  883. goto next;
  884. }
  885. }
  886. c = *entry_name_end;
  887. *entry_name_end = 0;
  888. if (hook (entry_name, entry_type, entry_item, hook_data))
  889. {
  890. *entry_name_end = c;
  891. grub_dprintf ("reiserfs", "Found : %s, type=%d\n",
  892. entry_name, entry_type);
  893. ret = 1;
  894. goto found;
  895. }
  896. *entry_name_end = c;
  897. next:
  898. ;
  899. }
  900. if (next_offset == 0)
  901. break;
  902. grub_reiserfs_set_key_offset (&(item_headers[block_position].key),
  903. next_offset);
  904. if (grub_reiserfs_get_item (data, &(item_headers[block_position].key),
  905. &directory_item, 1) != GRUB_ERR_NONE)
  906. goto fail;
  907. block_number = directory_item.block_number;
  908. block_position = directory_item.block_position;
  909. next_offset = directory_item.next_offset;
  910. }
  911. while (block_number);
  912. found:
  913. assert (grub_errno == GRUB_ERR_NONE);
  914. grub_free (block_header);
  915. return ret;
  916. fail:
  917. assert (grub_errno != GRUB_ERR_NONE);
  918. grub_free (block_header);
  919. return 0;
  920. }
  921. /****************************************************************************/
  922. /* grub api functions */
  923. /****************************************************************************/
  924. /* Open a file named NAME and initialize FILE. */
  925. static grub_err_t
  926. grub_reiserfs_open (struct grub_file *file, const char *name)
  927. {
  928. struct grub_reiserfs_data *data = 0;
  929. struct grub_fshelp_node root, *found = 0;
  930. struct grub_reiserfs_key key;
  931. grub_dl_ref (my_mod);
  932. data = grub_reiserfs_mount (file->device->disk);
  933. if (! data)
  934. goto fail;
  935. key.directory_id = grub_cpu_to_le32_compile_time (1);
  936. key.object_id = grub_cpu_to_le32_compile_time (2);
  937. key.u.v2.offset_type = 0;
  938. grub_reiserfs_set_key_type (&key, GRUB_REISERFS_DIRECTORY, 2);
  939. grub_reiserfs_set_key_offset (&key, 1);
  940. if (grub_reiserfs_get_item (data, &key, &root, 1) != GRUB_ERR_NONE)
  941. goto fail;
  942. if (root.block_number == 0)
  943. {
  944. grub_error (GRUB_ERR_BAD_FS, "unable to find root item");
  945. goto fail; /* Should never happen since checked at mount. */
  946. }
  947. grub_fshelp_find_file (name, &root, &found,
  948. grub_reiserfs_iterate_dir,
  949. grub_reiserfs_read_symlink, GRUB_FSHELP_REG);
  950. if (grub_errno)
  951. goto fail;
  952. file->size = found->size;
  953. grub_dprintf ("reiserfs", "file size : %d (%08x%08x)\n",
  954. (unsigned int) file->size,
  955. (unsigned int) (file->size >> 32), (unsigned int) file->size);
  956. file->offset = 0;
  957. file->data = found;
  958. return GRUB_ERR_NONE;
  959. fail:
  960. assert (grub_errno != GRUB_ERR_NONE);
  961. if (found != &root)
  962. grub_free (found);
  963. grub_free (data);
  964. grub_dl_unref (my_mod);
  965. return grub_errno;
  966. }
  967. static grub_ssize_t
  968. grub_reiserfs_read_real (struct grub_fshelp_node *node,
  969. grub_off_t off, char *buf, grub_size_t len,
  970. grub_disk_read_hook_t read_hook, void *read_hook_data)
  971. {
  972. unsigned int indirect_block, indirect_block_count;
  973. struct grub_reiserfs_key key;
  974. struct grub_reiserfs_data *data = node->data;
  975. struct grub_fshelp_node found;
  976. grub_uint16_t block_size = grub_le_to_cpu16 (data->superblock.block_size);
  977. grub_uint16_t item_size;
  978. grub_uint32_t *indirect_block_ptr = 0;
  979. grub_uint64_t current_key_offset = 1;
  980. grub_off_t initial_position, current_position, final_position, length;
  981. grub_disk_addr_t block;
  982. grub_off_t offset;
  983. key.directory_id = node->header.key.directory_id;
  984. key.object_id = node->header.key.object_id;
  985. key.u.v2.offset_type = 0;
  986. grub_reiserfs_set_key_type (&key, GRUB_REISERFS_ANY, 2);
  987. initial_position = off;
  988. current_position = 0;
  989. final_position = MIN (len + initial_position, node->size);
  990. grub_dprintf ("reiserfs",
  991. "Reading from %lld to %lld (%lld instead of requested %ld)\n",
  992. (unsigned long long) initial_position,
  993. (unsigned long long) final_position,
  994. (unsigned long long) (final_position - initial_position),
  995. (unsigned long) len);
  996. grub_reiserfs_set_key_offset (&key, initial_position + 1);
  997. if (grub_reiserfs_get_item (data, &key, &found, 0) != GRUB_ERR_NONE)
  998. goto fail;
  999. if (found.block_number == 0)
  1000. {
  1001. grub_error (GRUB_ERR_READ_ERROR, "offset %lld not found",
  1002. (unsigned long long) initial_position);
  1003. goto fail;
  1004. }
  1005. current_key_offset = grub_reiserfs_get_key_offset (&found.header.key);
  1006. current_position = current_key_offset - 1;
  1007. while (current_position < final_position)
  1008. {
  1009. grub_reiserfs_set_key_offset (&key, current_key_offset);
  1010. if (grub_reiserfs_get_item (data, &key, &found, 1) != GRUB_ERR_NONE)
  1011. goto fail;
  1012. if (found.block_number == 0)
  1013. goto fail;
  1014. item_size = grub_le_to_cpu16 (found.header.item_size);
  1015. switch (found.type)
  1016. {
  1017. case GRUB_REISERFS_DIRECT:
  1018. block = ((grub_disk_addr_t) found.block_number) * (block_size >> GRUB_DISK_SECTOR_BITS);
  1019. grub_dprintf ("reiserfs_blocktype", "D: %u\n", (unsigned) block);
  1020. if (initial_position < current_position + item_size)
  1021. {
  1022. offset = MAX ((signed) (initial_position - current_position), 0);
  1023. length = (MIN (item_size, final_position - current_position)
  1024. - offset);
  1025. grub_dprintf ("reiserfs",
  1026. "Reading direct block %u from %u to %u...\n",
  1027. (unsigned) block, (unsigned) offset,
  1028. (unsigned) (offset + length));
  1029. found.data->disk->read_hook = read_hook;
  1030. found.data->disk->read_hook_data = read_hook_data;
  1031. grub_disk_read (found.data->disk,
  1032. block,
  1033. offset
  1034. + grub_le_to_cpu16 (found.header.item_location),
  1035. length, buf);
  1036. found.data->disk->read_hook = 0;
  1037. if (grub_errno)
  1038. goto fail;
  1039. buf += length;
  1040. current_position += offset + length;
  1041. }
  1042. else
  1043. current_position += item_size;
  1044. break;
  1045. case GRUB_REISERFS_INDIRECT:
  1046. indirect_block_count = item_size / sizeof (*indirect_block_ptr);
  1047. indirect_block_ptr = grub_malloc (item_size);
  1048. if (! indirect_block_ptr)
  1049. goto fail;
  1050. grub_disk_read (found.data->disk,
  1051. found.block_number * (block_size >> GRUB_DISK_SECTOR_BITS),
  1052. grub_le_to_cpu16 (found.header.item_location),
  1053. item_size, indirect_block_ptr);
  1054. if (grub_errno)
  1055. goto fail;
  1056. found.data->disk->read_hook = read_hook;
  1057. found.data->disk->read_hook_data = read_hook_data;
  1058. for (indirect_block = 0;
  1059. indirect_block < indirect_block_count
  1060. && current_position < final_position;
  1061. indirect_block++)
  1062. {
  1063. block = grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) *
  1064. (block_size >> GRUB_DISK_SECTOR_BITS);
  1065. grub_dprintf ("reiserfs_blocktype", "I: %u\n", (unsigned) block);
  1066. if (current_position + block_size >= initial_position)
  1067. {
  1068. offset = MAX ((signed) (initial_position - current_position),
  1069. 0);
  1070. length = (MIN (block_size, final_position - current_position)
  1071. - offset);
  1072. grub_dprintf ("reiserfs",
  1073. "Reading indirect block %u from %u to %u...\n",
  1074. (unsigned) block, (unsigned) offset,
  1075. (unsigned) (offset + length));
  1076. #if 0
  1077. grub_dprintf ("reiserfs",
  1078. "\nib=%04d/%04d, ip=%d, cp=%d, fp=%d, off=%d, l=%d, tl=%d\n",
  1079. indirect_block + 1, indirect_block_count,
  1080. initial_position, current_position,
  1081. final_position, offset, length, len);
  1082. #endif
  1083. grub_disk_read (found.data->disk, block, offset, length, buf);
  1084. if (grub_errno)
  1085. goto fail;
  1086. buf += length;
  1087. current_position += offset + length;
  1088. }
  1089. else
  1090. current_position += block_size;
  1091. }
  1092. found.data->disk->read_hook = 0;
  1093. grub_free (indirect_block_ptr);
  1094. indirect_block_ptr = 0;
  1095. break;
  1096. default:
  1097. goto fail;
  1098. }
  1099. current_key_offset = current_position + 1;
  1100. }
  1101. grub_dprintf ("reiserfs",
  1102. "Have successfully read %lld bytes (%ld requested)\n",
  1103. (unsigned long long) (current_position - initial_position),
  1104. (unsigned long) len);
  1105. return current_position - initial_position;
  1106. #if 0
  1107. switch (found.type)
  1108. {
  1109. case GRUB_REISERFS_DIRECT:
  1110. read_length = MIN (len, item_size - file->offset);
  1111. grub_disk_read (found.data->disk,
  1112. (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
  1113. grub_le_to_cpu16 (found.header.item_location) + file->offset,
  1114. read_length, buf);
  1115. if (grub_errno)
  1116. goto fail;
  1117. break;
  1118. case GRUB_REISERFS_INDIRECT:
  1119. indirect_block_count = item_size / sizeof (*indirect_block_ptr);
  1120. indirect_block_ptr = grub_malloc (item_size);
  1121. if (!indirect_block_ptr)
  1122. goto fail;
  1123. grub_disk_read (found.data->disk,
  1124. (found.block_number * block_size) / GRUB_DISK_SECTOR_SIZE,
  1125. grub_le_to_cpu16 (found.header.item_location),
  1126. item_size, (char *) indirect_block_ptr);
  1127. if (grub_errno)
  1128. goto fail;
  1129. len = MIN (len, file->size - file->offset);
  1130. for (indirect_block = file->offset / block_size;
  1131. indirect_block < indirect_block_count && read_length < len;
  1132. indirect_block++)
  1133. {
  1134. read = MIN (block_size, len - read_length);
  1135. grub_disk_read (found.data->disk,
  1136. (grub_le_to_cpu32 (indirect_block_ptr[indirect_block]) * block_size) / GRUB_DISK_SECTOR_SIZE,
  1137. file->offset % block_size, read,
  1138. ((void *) buf) + read_length);
  1139. if (grub_errno)
  1140. goto fail;
  1141. read_length += read;
  1142. }
  1143. grub_free (indirect_block_ptr);
  1144. break;
  1145. default:
  1146. goto fail;
  1147. }
  1148. return read_length;
  1149. #endif
  1150. fail:
  1151. grub_free (indirect_block_ptr);
  1152. return -1;
  1153. }
  1154. static grub_ssize_t
  1155. grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len)
  1156. {
  1157. return grub_reiserfs_read_real (file->data, file->offset, buf, len,
  1158. file->read_hook, file->read_hook_data);
  1159. }
  1160. /* Close the file FILE. */
  1161. static grub_err_t
  1162. grub_reiserfs_close (grub_file_t file)
  1163. {
  1164. struct grub_fshelp_node *node = file->data;
  1165. struct grub_reiserfs_data *data = node->data;
  1166. grub_free (data);
  1167. grub_free (node);
  1168. grub_dl_unref (my_mod);
  1169. return GRUB_ERR_NONE;
  1170. }
  1171. /* Context for grub_reiserfs_dir. */
  1172. struct grub_reiserfs_dir_ctx
  1173. {
  1174. grub_fs_dir_hook_t hook;
  1175. void *hook_data;
  1176. };
  1177. /* Helper for grub_reiserfs_dir. */
  1178. static int
  1179. grub_reiserfs_dir_iter (const char *filename,
  1180. enum grub_fshelp_filetype filetype,
  1181. grub_fshelp_node_t node, void *data)
  1182. {
  1183. struct grub_reiserfs_dir_ctx *ctx = data;
  1184. struct grub_dirhook_info info;
  1185. grub_memset (&info, 0, sizeof (info));
  1186. info.dir = ((filetype & GRUB_FSHELP_TYPE_MASK) == GRUB_FSHELP_DIR);
  1187. info.mtimeset = 1;
  1188. info.mtime = node->mtime;
  1189. grub_free (node);
  1190. return ctx->hook (filename, &info, ctx->hook_data);
  1191. }
  1192. /* Call HOOK with each file under DIR. */
  1193. static grub_err_t
  1194. grub_reiserfs_dir (grub_device_t device, const char *path,
  1195. grub_fs_dir_hook_t hook, void *hook_data)
  1196. {
  1197. struct grub_reiserfs_dir_ctx ctx = { hook, hook_data };
  1198. struct grub_reiserfs_data *data = 0;
  1199. struct grub_fshelp_node root, *found;
  1200. struct grub_reiserfs_key root_key;
  1201. grub_dl_ref (my_mod);
  1202. data = grub_reiserfs_mount (device->disk);
  1203. if (! data)
  1204. goto fail;
  1205. root_key.directory_id = grub_cpu_to_le32_compile_time (1);
  1206. root_key.object_id = grub_cpu_to_le32_compile_time (2);
  1207. root_key.u.v2.offset_type = 0;
  1208. grub_reiserfs_set_key_type (&root_key, GRUB_REISERFS_DIRECTORY, 2);
  1209. grub_reiserfs_set_key_offset (&root_key, 1);
  1210. if (grub_reiserfs_get_item (data, &root_key, &root, 1) != GRUB_ERR_NONE)
  1211. goto fail;
  1212. if (root.block_number == 0)
  1213. {
  1214. grub_error(GRUB_ERR_BAD_FS, "root not found");
  1215. goto fail;
  1216. }
  1217. grub_fshelp_find_file (path, &root, &found, grub_reiserfs_iterate_dir,
  1218. grub_reiserfs_read_symlink, GRUB_FSHELP_DIR);
  1219. if (grub_errno)
  1220. goto fail;
  1221. grub_reiserfs_iterate_dir (found, grub_reiserfs_dir_iter, &ctx);
  1222. grub_free (data);
  1223. grub_dl_unref (my_mod);
  1224. return GRUB_ERR_NONE;
  1225. fail:
  1226. grub_free (data);
  1227. grub_dl_unref (my_mod);
  1228. return grub_errno;
  1229. }
  1230. /* Return the label of the device DEVICE in LABEL. The label is
  1231. returned in a grub_malloc'ed buffer and should be freed by the
  1232. caller. */
  1233. static grub_err_t
  1234. grub_reiserfs_label (grub_device_t device, char **label)
  1235. {
  1236. struct grub_reiserfs_data *data;
  1237. grub_disk_t disk = device->disk;
  1238. grub_dl_ref (my_mod);
  1239. data = grub_reiserfs_mount (disk);
  1240. if (data)
  1241. {
  1242. *label = grub_strndup (data->superblock.label,
  1243. sizeof (data->superblock.label));
  1244. }
  1245. else
  1246. *label = NULL;
  1247. grub_dl_unref (my_mod);
  1248. grub_free (data);
  1249. return grub_errno;
  1250. }
  1251. static grub_err_t
  1252. grub_reiserfs_uuid (grub_device_t device, char **uuid)
  1253. {
  1254. struct grub_reiserfs_data *data;
  1255. grub_disk_t disk = device->disk;
  1256. grub_dl_ref (my_mod);
  1257. *uuid = NULL;
  1258. data = grub_reiserfs_mount (disk);
  1259. if (data)
  1260. {
  1261. unsigned i;
  1262. for (i = 0; i < ARRAY_SIZE (data->superblock.uuid); i++)
  1263. if (data->superblock.uuid[i])
  1264. break;
  1265. if (i < ARRAY_SIZE (data->superblock.uuid))
  1266. *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
  1267. grub_be_to_cpu16 (data->superblock.uuid[0]),
  1268. grub_be_to_cpu16 (data->superblock.uuid[1]),
  1269. grub_be_to_cpu16 (data->superblock.uuid[2]),
  1270. grub_be_to_cpu16 (data->superblock.uuid[3]),
  1271. grub_be_to_cpu16 (data->superblock.uuid[4]),
  1272. grub_be_to_cpu16 (data->superblock.uuid[5]),
  1273. grub_be_to_cpu16 (data->superblock.uuid[6]),
  1274. grub_be_to_cpu16 (data->superblock.uuid[7]));
  1275. }
  1276. grub_dl_unref (my_mod);
  1277. grub_free (data);
  1278. return grub_errno;
  1279. }
  1280. static struct grub_fs grub_reiserfs_fs =
  1281. {
  1282. .name = "reiserfs",
  1283. .fs_dir = grub_reiserfs_dir,
  1284. .fs_open = grub_reiserfs_open,
  1285. .fs_read = grub_reiserfs_read,
  1286. .fs_close = grub_reiserfs_close,
  1287. .fs_label = grub_reiserfs_label,
  1288. .fs_uuid = grub_reiserfs_uuid,
  1289. #ifdef GRUB_UTIL
  1290. .reserved_first_sector = 1,
  1291. .blocklist_install = 1,
  1292. #endif
  1293. .next = 0
  1294. };
  1295. GRUB_MOD_INIT(reiserfs)
  1296. {
  1297. if (!grub_is_lockdown ())
  1298. {
  1299. grub_reiserfs_fs.mod = mod;
  1300. grub_fs_register (&grub_reiserfs_fs);
  1301. }
  1302. my_mod = mod;
  1303. }
  1304. GRUB_MOD_FINI(reiserfs)
  1305. {
  1306. if (!grub_is_lockdown ())
  1307. grub_fs_unregister (&grub_reiserfs_fs);
  1308. }