reiserfs.c 46 KB

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