e2lib.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  1. /* This is a library of functions that allow user-level programs to
  2. * read and manipulate ext2 file systems. For convenience sake,
  3. * this library maintains a lot of state information in static
  4. * variables; therefore, it's not reentrant. We don't care for
  5. * our applications 8-)
  6. */
  7. #include <fcntl.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <sys/types.h>
  13. #include <sys/stat.h>
  14. #include <bio.h>
  15. #include <e2lib.h>
  16. #define MAX_OPEN_FILES 8
  17. int fd = -1;
  18. struct ext2_super_block sb;
  19. struct ext2_group_desc *gds;
  20. int ngroups = 0;
  21. int blocksize; /* Block size of this fs */
  22. int directlim; /* Maximum direct blkno */
  23. int ind1lim; /* Maximum single-indir blkno */
  24. int ind2lim; /* Maximum double-indir blkno */
  25. int ptrs_per_blk; /* ptrs/indirect block */
  26. char filename[256];
  27. int readonly; /* Is this FS read-only? */
  28. int verbose = 0;
  29. int big_endian = 0;
  30. static void ext2_ifree(int ino);
  31. static void ext2_free_indirect(int indirect_blkno, int level);
  32. struct inode_table_entry {
  33. struct ext2_inode inode;
  34. int inumber;
  35. int free;
  36. unsigned short old_mode;
  37. } inode_table[MAX_OPEN_FILES];
  38. /* Utility functions to byte-swap 16 and 32 bit quantities... */
  39. unsigned short
  40. swap16 (unsigned short s)
  41. {
  42. return((unsigned short)( ((s << 8) & 0xff00) | ((s >> 8) & 0x00ff)));
  43. }
  44. unsigned int
  45. swap32 (unsigned int i)
  46. {
  47. return((unsigned int)(
  48. ((i << 24) & 0xff000000) |
  49. ((i << 8) & 0x00ff0000) |
  50. ((i >> 8) & 0x0000ff00) |
  51. ((i >> 24) & 0x000000ff)) );
  52. }
  53. void
  54. ext2_swap_sb (struct ext2_super_block *sb)
  55. {
  56. sb->s_inodes_count = swap32(sb->s_inodes_count);
  57. sb->s_blocks_count = swap32(sb->s_blocks_count);
  58. sb->s_r_blocks_count = swap32(sb->s_r_blocks_count);
  59. sb->s_free_blocks_count = swap32(sb->s_free_blocks_count);
  60. sb->s_free_inodes_count = swap32(sb->s_free_inodes_count);
  61. sb->s_first_data_block = swap32(sb->s_first_data_block);
  62. sb->s_log_block_size = swap32(sb->s_log_block_size);
  63. sb->s_log_frag_size = swap32(sb->s_log_frag_size);
  64. sb->s_blocks_per_group = swap32(sb->s_blocks_per_group);
  65. sb->s_frags_per_group = swap32(sb->s_frags_per_group);
  66. sb->s_inodes_per_group = swap32(sb->s_inodes_per_group);
  67. sb->s_mtime = swap32(sb->s_mtime);
  68. sb->s_wtime = swap32(sb->s_wtime);
  69. sb->s_mnt_count = swap16(sb->s_mnt_count);
  70. sb->s_max_mnt_count = swap16(sb->s_max_mnt_count);
  71. sb->s_magic = swap16(sb->s_magic);
  72. sb->s_state = swap16(sb->s_state);
  73. sb->s_errors = swap16(sb->s_errors);
  74. sb->s_pad = swap16(sb->s_pad);
  75. sb->s_lastcheck = swap32(sb->s_lastcheck);
  76. sb->s_checkinterval = swap32(sb->s_checkinterval);
  77. }
  78. void
  79. ext2_swap_gd (struct ext2_group_desc *gd)
  80. {
  81. gd->bg_block_bitmap = swap32(gd->bg_block_bitmap);
  82. gd->bg_inode_bitmap = swap32(gd->bg_inode_bitmap);
  83. gd->bg_inode_table = swap32(gd->bg_inode_table);
  84. gd->bg_free_blocks_count = swap16(gd->bg_free_blocks_count);
  85. gd->bg_free_inodes_count = swap16(gd->bg_free_inodes_count);
  86. gd->bg_used_dirs_count = swap16(gd->bg_used_dirs_count);
  87. gd->bg_pad = swap16(gd->bg_pad);
  88. }
  89. void
  90. ext2_swap_inode (struct ext2_inode *ip)
  91. {
  92. int i;
  93. ip->i_mode = swap16(ip->i_mode);
  94. ip->i_uid = swap16(ip->i_uid);
  95. ip->i_size = swap32(ip->i_size);
  96. ip->i_atime = swap32(ip->i_atime);
  97. ip->i_ctime = swap32(ip->i_ctime);
  98. ip->i_mtime = swap32(ip->i_mtime);
  99. ip->i_dtime = swap32(ip->i_dtime);
  100. ip->i_gid = swap16(ip->i_gid);
  101. ip->i_links_count = swap16(ip->i_links_count);
  102. ip->i_blocks = swap32(ip->i_blocks);
  103. ip->i_flags = swap32(ip->i_flags);
  104. ip->i_reserved1 = swap32(ip->i_reserved1);
  105. for(i = 0; i < EXT2_N_BLOCKS; i++) {
  106. ip->i_block[i] = swap32(ip->i_block[i]);
  107. }
  108. ip->i_version = swap32(ip->i_version);
  109. ip->i_file_acl = swap32(ip->i_file_acl);
  110. ip->i_dir_acl = swap32(ip->i_dir_acl);
  111. ip->i_faddr = swap32(ip->i_faddr);
  112. ip->i_pad1 = swap16(ip->i_pad1);
  113. }
  114. /* Initialize an ext2 filesystem; this is sort-of the same idea as
  115. * "mounting" it. Read in the relevant control structures and
  116. * make them available to the user. Returns 0 if successful, -1 on
  117. * failure.
  118. */
  119. int
  120. ext2_init (char * name, int access)
  121. {
  122. int i;
  123. /* Initialize the inode table */
  124. for(i = 0; i < MAX_OPEN_FILES; i++) {
  125. inode_table[i].free = 1;
  126. inode_table[i].inumber = 0;
  127. }
  128. if((access != O_RDONLY) && (access != O_RDWR)) {
  129. fprintf(stderr,
  130. "ext2_init: Access must be O_RDONLY or O_RDWR, not %d\n",
  131. access);
  132. return(-1);
  133. }
  134. /* Open the device/file */
  135. fd = open(name, access);
  136. if(fd < 0) {
  137. perror(filename);
  138. return(-1);
  139. }
  140. if(access == O_RDONLY) {
  141. readonly = 1;
  142. }
  143. /* Read in the first superblock */
  144. lseek(fd, EXT2_MIN_BLOCK_SIZE, SEEK_SET);
  145. if(read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
  146. perror("ext2 sb read");
  147. close(fd);
  148. return(-1);
  149. }
  150. if((sb.s_magic != EXT2_SUPER_MAGIC) && (sb.s_magic != EXT2_SUPER_BIGMAGIC)) {
  151. fprintf(stderr, "ext2 bad magic 0x%x\n", sb.s_magic);
  152. close(fd);
  153. return(-1);
  154. }
  155. if(sb.s_magic == EXT2_SUPER_BIGMAGIC) {
  156. big_endian = 1;
  157. /* Byte-swap the fields in the superblock... */
  158. ext2_swap_sb(&sb);
  159. }
  160. if(sb.s_first_data_block != 1) {
  161. fprintf(stderr,
  162. "Brain-damaged utils can't deal with a filesystem\nwhere s_first_data_block != 1.\nRe-initialize the filesystem\n");
  163. close(fd);
  164. return(-1);
  165. }
  166. ngroups = (sb.s_blocks_count+sb.s_blocks_per_group-1)/sb.s_blocks_per_group;
  167. gds = (struct ext2_group_desc *)
  168. malloc((size_t)(ngroups * sizeof(struct ext2_group_desc)));
  169. /* Read in the group descriptors (immediately follows superblock) */
  170. if ((size_t) read(fd, gds, ngroups * sizeof(struct ext2_group_desc))
  171. != (ngroups * sizeof(struct ext2_group_desc)))
  172. {
  173. perror("ext2_init: group desc read error");
  174. return(-1);
  175. }
  176. if(big_endian) {
  177. for(i = 0; i < ngroups; i++) {
  178. ext2_swap_gd(&(gds[i]));
  179. }
  180. }
  181. strcpy(filename, name);
  182. /* Calculate direct/indirect block limits for this file system
  183. * (blocksize dependent)
  184. */
  185. blocksize = EXT2_BLOCK_SIZE(&sb);
  186. directlim = EXT2_NDIR_BLOCKS - 1;
  187. ptrs_per_blk = blocksize/sizeof(unsigned int);
  188. ind1lim = ptrs_per_blk + directlim;
  189. ind2lim = (ptrs_per_blk * ptrs_per_blk) + directlim;
  190. if(getenv("EXT2_VERBOSE")) {
  191. verbose = 1;
  192. }
  193. binit(fd, blocksize);
  194. if(verbose) {
  195. printf("Initialized filesystem %s\n", filename);
  196. printf(" %d blocks (%dKb), %d free (%dKb)\n",
  197. sb.s_blocks_count, (sb.s_blocks_count * blocksize)/1024,
  198. sb.s_free_blocks_count,
  199. (sb.s_free_blocks_count * blocksize)/1024);
  200. printf(" %d inodes, %d free\n",
  201. sb.s_inodes_count, sb.s_free_inodes_count);
  202. printf(" %d groups, %d blocks/group\n",
  203. ngroups, sb.s_blocks_per_group);
  204. }
  205. return(0);
  206. }
  207. int
  208. ext2_blocksize (void)
  209. {
  210. return blocksize;
  211. }
  212. int
  213. ext2_total_blocks (void)
  214. {
  215. return sb.s_blocks_count;
  216. }
  217. int
  218. ext2_free_blocks (void)
  219. {
  220. return sb.s_free_blocks_count;
  221. }
  222. int
  223. ext2_total_inodes (void)
  224. {
  225. return sb.s_inodes_count;
  226. }
  227. int
  228. ext2_free_inodes (void)
  229. {
  230. return sb.s_free_inodes_count;
  231. }
  232. /* Call this when we're all done with the file system. This will write
  233. * back any superblock and group changes to the file system.
  234. */
  235. void
  236. ext2_close (void)
  237. {
  238. int i;
  239. int errors = 0;
  240. int blocks_per_group = sb.s_blocks_per_group;
  241. if(!readonly) {
  242. if(big_endian) {
  243. ext2_swap_sb(&sb);
  244. for(i = 0; i < ngroups; i++) {
  245. ext2_swap_gd(&(gds[i]));
  246. }
  247. }
  248. for(i = 0; i < ngroups; i++) {
  249. lseek(fd, ((i*blocks_per_group)+1)*blocksize, SEEK_SET);
  250. if(write(fd, &sb, sizeof(sb)) != sizeof(sb)) {
  251. perror("sb write");
  252. errors = 1;
  253. }
  254. if ((size_t) write(fd, gds, ngroups*sizeof(struct ext2_group_desc))
  255. != ngroups*sizeof(struct ext2_group_desc))
  256. {
  257. perror("gds write");
  258. errors = 1;
  259. }
  260. bflush();
  261. }
  262. }
  263. close(fd);
  264. if(errors) {
  265. fprintf(stderr, "Errors encountered while updating %s\n", filename);
  266. fprintf(stderr, "e2fsck is STRONGLY recommended!\n");
  267. }
  268. }
  269. /* Read the specified inode from the disk and return it to the user.
  270. * Returns NULL if the inode can't be read...
  271. */
  272. struct ext2_inode *
  273. ext2_iget (int ino)
  274. {
  275. int i;
  276. struct ext2_inode * ip = NULL;
  277. struct inode_table_entry * itp = NULL;
  278. int group;
  279. int blkoffset;
  280. int byteoffset;
  281. char inobuf[EXT2_MAX_BLOCK_SIZE];
  282. for(i = 0; i < MAX_OPEN_FILES; i++) {
  283. if(inode_table[i].free) {
  284. itp = &(inode_table[i]);
  285. ip = &(itp->inode);
  286. break;
  287. }
  288. }
  289. if(!ip) {
  290. fprintf(stderr, "ext2_iget: no free inodes\n");
  291. return(NULL);
  292. }
  293. group = ino / sb.s_inodes_per_group;
  294. blkoffset = (gds[group].bg_inode_table * blocksize);
  295. byteoffset = ((ino-1) % sb.s_inodes_per_group) * sizeof(struct ext2_inode);
  296. blkoffset += ((byteoffset / blocksize) * blocksize);
  297. byteoffset = (byteoffset % blocksize);
  298. bread(blkoffset/blocksize, inobuf);
  299. memcpy(ip, &(inobuf[byteoffset]), sizeof(struct ext2_inode));
  300. if(big_endian) {
  301. ext2_swap_inode(ip);
  302. }
  303. /* Yes, this is ugly, but it makes iput SOOO much easier 8-) */
  304. itp->free = 0;
  305. itp->inumber = ino;
  306. itp->old_mode = ip->i_mode;
  307. return(ip);
  308. }
  309. /* Put the specified inode back on the disk where it came from. */
  310. void
  311. ext2_iput (struct ext2_inode *ip)
  312. {
  313. int group;
  314. int blkoffset;
  315. int byteoffset;
  316. int ino;
  317. struct inode_table_entry *itp;
  318. char inobuf[EXT2_MAX_BLOCK_SIZE];
  319. int inode_mode;
  320. itp = (struct inode_table_entry *)ip;
  321. ino = itp->inumber;
  322. if(ip->i_links_count == 0) {
  323. ext2_ifree(itp->inumber);
  324. }
  325. itp->inumber = 0;
  326. if(!readonly) {
  327. group = ino / sb.s_inodes_per_group;
  328. blkoffset = (gds[group].bg_inode_table * blocksize);
  329. byteoffset = ((ino-1) % sb.s_inodes_per_group) * sizeof(struct ext2_inode);
  330. blkoffset += (byteoffset / blocksize) * blocksize;
  331. byteoffset = byteoffset % blocksize;
  332. inode_mode = ip->i_mode;
  333. bread(blkoffset/blocksize, inobuf);
  334. if(big_endian) {
  335. ext2_swap_inode(ip);
  336. }
  337. memcpy(&(inobuf[byteoffset]), ip, sizeof(struct ext2_inode));
  338. bwrite(blkoffset/blocksize, inobuf);
  339. if(S_ISDIR(itp->old_mode) && !S_ISDIR(inode_mode)) {
  340. /* We deleted a directory */
  341. gds[group].bg_used_dirs_count--;
  342. }
  343. if(!S_ISDIR(itp->old_mode) && S_ISDIR(inode_mode)) {
  344. /* We created a directory */
  345. gds[group].bg_used_dirs_count++;
  346. }
  347. }
  348. itp->free = 1;
  349. }
  350. #define BITS_PER_LONG (8*sizeof(int))
  351. static int
  352. find_first_zero_bit (unsigned int * addr, unsigned size)
  353. {
  354. unsigned lwsize;
  355. unsigned int *ap = (unsigned int *)addr;
  356. unsigned int mask;
  357. unsigned int longword, bit;
  358. unsigned int lwval;
  359. if (!size)
  360. return 0;
  361. /* Convert "size" to a whole number of longwords... */
  362. lwsize = (size + BITS_PER_LONG - 1) >> 5;
  363. for (longword = 0; longword < lwsize; longword++, ap++) {
  364. if(*ap != 0xffffffff) {
  365. lwval = big_endian ? swap32(*ap) : *ap;
  366. for (bit = 0, mask = 1; bit < BITS_PER_LONG; bit++, mask <<= 1)
  367. {
  368. if ((lwval & mask) == 0) {
  369. return (longword*BITS_PER_LONG) + bit;
  370. }
  371. }
  372. }
  373. }
  374. return size;
  375. }
  376. static void
  377. set_bit (unsigned int *addr, int bitno)
  378. {
  379. if(big_endian) {
  380. int lwval;
  381. lwval = swap32(addr[bitno/BITS_PER_LONG]);
  382. lwval |= (1 << (bitno % BITS_PER_LONG));
  383. addr[bitno/BITS_PER_LONG] = swap32(lwval);
  384. }
  385. else {
  386. addr[bitno / BITS_PER_LONG] |= (1 << (bitno % BITS_PER_LONG));
  387. }
  388. }
  389. static void
  390. clear_bit (unsigned int *addr, int bitno)
  391. {
  392. if(big_endian) {
  393. int lwval;
  394. lwval = swap32(addr[bitno/BITS_PER_LONG]);
  395. lwval &= ~((unsigned int)(1 << (bitno % BITS_PER_LONG)));
  396. addr[bitno/BITS_PER_LONG] = swap32(lwval);
  397. }
  398. else {
  399. addr[bitno / BITS_PER_LONG] &=
  400. ~((unsigned int)(1 << (bitno % BITS_PER_LONG)));
  401. }
  402. }
  403. /* Allocate a block from the file system. Brain-damaged implementation;
  404. * doesn't even TRY to do load-balancing among groups... just grabs the
  405. * first block it can find...
  406. */
  407. int
  408. ext2_balloc (void)
  409. {
  410. unsigned int blk, blockmap[256];
  411. int i;
  412. if(readonly) {
  413. fprintf(stderr, "ext2_balloc: readonly filesystem\n");
  414. return(0);
  415. }
  416. for(i = 0; i < ngroups; i++) {
  417. if(gds[i].bg_free_blocks_count > 0) {
  418. bread(gds[i].bg_block_bitmap, blockmap);
  419. blk = find_first_zero_bit(blockmap, sb.s_blocks_per_group);
  420. if (blk == 0 || blk == sb.s_blocks_per_group) {
  421. fprintf(stderr,
  422. "group %d has %d blocks free but none in bitmap?\n",
  423. i, gds[i].bg_free_blocks_count);
  424. continue;
  425. }
  426. set_bit(blockmap, blk);
  427. bwrite(gds[i].bg_block_bitmap, blockmap);
  428. gds[i].bg_free_blocks_count--;
  429. sb.s_free_blocks_count--;
  430. blk = blk + (i*sb.s_blocks_per_group)+1;
  431. if(blk == 0) {
  432. fprintf(stderr, "ext2_balloc: blk == 0?\n");
  433. }
  434. return(blk);
  435. }
  436. }
  437. if(verbose) {
  438. printf("ext2_balloc: can't find a free block\n");
  439. }
  440. return(0);
  441. }
  442. /* Deallocate a block */
  443. void
  444. ext2_bfree (int blk)
  445. {
  446. int i;
  447. unsigned int blockmap[256];
  448. /* Find which group this block is in */
  449. i = (blk-1) / sb.s_blocks_per_group;
  450. /* Read the block map */
  451. bread(gds[i].bg_block_bitmap, blockmap);
  452. /* Clear the appropriate bit */
  453. clear_bit(blockmap, (blk-1) % sb.s_blocks_per_group);
  454. /* Write the block map back out */
  455. bwrite(gds[i].bg_block_bitmap, blockmap);
  456. /* Update free block counts. */
  457. gds[i].bg_free_blocks_count++;
  458. sb.s_free_blocks_count++;
  459. }
  460. /* Allocate a contiguous range of blocks. This is used ONLY for
  461. * initializing the bootstrapper. It uses a simple-minded algorithm
  462. * that works best on a clean or nearly clean file system... we
  463. * chunk through the bitmap a longword at a time. Only if the whole
  464. * longword indicates free blocks do we use it. On a 32-bit system,
  465. * this means we allocate blocks only in units of 32.
  466. */
  467. int
  468. ext2_contiguous_balloc (int nblocks)
  469. {
  470. int i, j;
  471. int firstlong, lastlong;
  472. int longs_needed;
  473. int longs_per_group;
  474. int blk;
  475. unsigned int blockmap[256];
  476. if(readonly) {
  477. fprintf(stderr, "ext2_contiguous_balloc: readonly filesystem\n");
  478. return(0);
  479. }
  480. /* Compute how many longwords we need to fulfill this request */
  481. longs_needed = (nblocks + BITS_PER_LONG - 1) / BITS_PER_LONG;
  482. longs_per_group = sb.s_blocks_per_group/BITS_PER_LONG;
  483. for(i = 0; i < ngroups; i++) {
  484. /* Don't even bother if this group doesn't have enough blocks! */
  485. if(gds[i].bg_free_blocks_count >= nblocks) {
  486. /* Get the block map. */
  487. bread(gds[i].bg_block_bitmap, blockmap);
  488. /* Find a run of blocks */
  489. firstlong = 0;
  490. do {
  491. for(; firstlong < longs_per_group; firstlong++) {
  492. if(blockmap[firstlong] == 0) break;
  493. }
  494. if(firstlong == longs_per_group) {
  495. /* No such thing in this group; try another! */
  496. break;
  497. }
  498. for(lastlong = firstlong; lastlong < longs_per_group;
  499. lastlong++) {
  500. if(blockmap[lastlong] != 0) break;
  501. }
  502. if((lastlong-firstlong) < longs_needed) {
  503. firstlong = lastlong;
  504. }
  505. } while((lastlong-firstlong) < longs_needed);
  506. /* If we got all the way through the block map,
  507. * try another group.
  508. */
  509. if(firstlong == longs_per_group) {
  510. continue;
  511. }
  512. /* If we get here, then we know that we have a run
  513. * that will fit our allocation. Allocate the *actual*
  514. * blocks that we need!
  515. */
  516. blk = firstlong * BITS_PER_LONG;
  517. for(j = 0; j < nblocks; j++) {
  518. set_bit(blockmap, blk+j);
  519. }
  520. bwrite(gds[i].bg_block_bitmap, blockmap);
  521. gds[i].bg_free_blocks_count -= nblocks;
  522. sb.s_free_blocks_count -= nblocks;
  523. blk = blk + (i*sb.s_blocks_per_group)+1;
  524. if(verbose) {
  525. printf("ext2_contiguous_balloc: allocated %d blks @%d\n",
  526. nblocks, blk);
  527. }
  528. return(blk);
  529. }
  530. }
  531. if(verbose) {
  532. printf("ext2_contiguous_balloc: can't find %d contiguous free blocks\n", nblocks);
  533. }
  534. return(0);
  535. }
  536. /* Pre-allocate contiguous blocks to the specified inode. Note that the
  537. * DATA blocks must be contiguous; indirect blocks can come from anywhere.
  538. * This is for the benefit of the bootstrap loader.
  539. * If successful, this routine returns the block number of the first
  540. * data block of the file. Otherwise, it returns -1.
  541. */
  542. int
  543. ext2_fill_contiguous (struct ext2_inode * ip, int nblocks)
  544. {
  545. int iblkno = 0;
  546. int firstblock;
  547. int i;
  548. unsigned int *lp = NULL;
  549. char blkbuf[EXT2_MAX_BLOCK_SIZE];
  550. /* For simplicity's sake, we only allow single indirection
  551. * here. We shouldn't need more than this anyway!
  552. */
  553. if(nblocks > ind1lim) {
  554. fprintf(stderr,
  555. "ext2_fill_contiguous: file size too big (%d); cannot exceed %d\n",
  556. nblocks, ind1lim);
  557. return(-1);
  558. }
  559. /* First, try to allocate the data blocks */
  560. firstblock = ext2_contiguous_balloc(nblocks);
  561. if(firstblock == 0) {
  562. fprintf(stderr,
  563. "ext2_fill_contiguous: Cannot allocate %d contiguous blocks\n", nblocks);
  564. return(-1);
  565. }
  566. ip->i_blocks = nblocks * (blocksize/512);
  567. /* If we need the indirect block, then allocate it now. */
  568. if(nblocks > directlim) {
  569. iblkno = ext2_balloc();
  570. if(iblkno == 0) {
  571. /* Should rarely happen! */
  572. fprintf(stderr,
  573. "ext2_fill_contiguous: cannot allocate indirect block\n");
  574. for(i = 0; i < nblocks; i++) {
  575. ext2_bfree(i);
  576. }
  577. return(-1);
  578. }
  579. ip->i_blocks += (blocksize/512);
  580. /* Point to indirect block buffer, in case we need it! */
  581. lp = (unsigned int *)blkbuf;
  582. for(i = 0; i < ptrs_per_blk; i++) {
  583. lp[i] = 0;
  584. }
  585. ip->i_block[EXT2_IND_BLOCK] = iblkno;
  586. }
  587. /* All set... let's roll! */
  588. ip->i_size = nblocks * blocksize;
  589. for(i = 0; i < nblocks; i++) {
  590. if(i < EXT2_NDIR_BLOCKS) {
  591. ip->i_block[i] = firstblock+i;
  592. }
  593. else {
  594. *lp++ = big_endian ? swap32(firstblock+i) : firstblock+i;
  595. }
  596. }
  597. /* Write back the indirect block if necessary... */
  598. if(iblkno) {
  599. bwrite(iblkno, blkbuf);
  600. }
  601. return(firstblock);
  602. }
  603. /* Write out a boot block for this file system. The caller
  604. * should have instantiated the block.
  605. */
  606. void
  607. ext2_write_bootblock (char *bb)
  608. {
  609. bwrite(0, bb);
  610. }
  611. /* Allocate an inode from the file system. Brain-damaged implementation;
  612. * doesn't even TRY to do load-balancing among groups... just grabs the
  613. * first inode it can find...
  614. */
  615. int
  616. ext2_ialloc (void)
  617. {
  618. unsigned int inodemap[256];
  619. int i, ino;
  620. if(readonly) {
  621. return(0);
  622. }
  623. for(i = 0; i < ngroups; i++) {
  624. if(gds[i].bg_free_inodes_count > 4) {
  625. /* leave a few inodes in each group for slop... */
  626. bread(gds[i].bg_inode_bitmap, inodemap);
  627. ino = find_first_zero_bit(inodemap, sb.s_inodes_per_group);
  628. if (ino == 0 || (unsigned) ino == sb.s_inodes_per_group) {
  629. fprintf(stderr,
  630. "group %d has %d inodes free but none in bitmap?\n",
  631. i, gds[i].bg_free_inodes_count);
  632. continue;
  633. }
  634. set_bit(inodemap, ino);
  635. bwrite(gds[i].bg_inode_bitmap, inodemap);
  636. gds[i].bg_free_inodes_count--;
  637. sb.s_free_inodes_count--;
  638. ino = ino + (i*sb.s_inodes_per_group) + 1;
  639. return ino;
  640. }
  641. }
  642. return 0;
  643. }
  644. /* Deallocate an inode */
  645. static void
  646. ext2_ifree (int ino)
  647. {
  648. int i;
  649. unsigned int inodemap[256];
  650. /* Find which group this inode is in */
  651. i = (ino-1) / sb.s_inodes_per_group;
  652. /* Read the inode map */
  653. bread(gds[i].bg_inode_bitmap, inodemap);
  654. /* Clear the appropriate bit */
  655. clear_bit(inodemap, (ino-1) % sb.s_inodes_per_group);
  656. /* Write the inode map back out */
  657. bwrite(gds[i].bg_inode_bitmap, inodemap);
  658. /* Update free inode counts. */
  659. gds[i].bg_free_inodes_count++;
  660. sb.s_free_inodes_count++;
  661. }
  662. /* Map a block offset into a file into an absolute block number.
  663. * (traverse the indirect blocks if necessary). Note: Double-indirect
  664. * blocks allow us to map over 64Mb on a 1k file system. Therefore, for
  665. * our purposes, we will NOT bother with triple indirect blocks.
  666. *
  667. * The "allocate" argument is set if we want to *allocate* a block
  668. * and we don't already have one allocated.
  669. */
  670. int
  671. ext2_blkno (struct ext2_inode *ip, int blkoff, int allocate)
  672. {
  673. unsigned int *lp;
  674. int blkno;
  675. int iblkno;
  676. int diblkno;
  677. char blkbuf[EXT2_MAX_BLOCK_SIZE];
  678. if(allocate && readonly) {
  679. fprintf(stderr, "ext2_blkno: Cannot allocate on a readonly file system!\n");
  680. return(0);
  681. }
  682. lp = (unsigned int *)blkbuf;
  683. /* If it's a direct block, it's easy! */
  684. if(blkoff <= directlim) {
  685. if((ip->i_block[blkoff] == 0) && allocate) {
  686. ip->i_block[blkoff] = ext2_balloc();
  687. if(verbose) {
  688. printf("Allocated data block %d\n", ip->i_block[blkoff]);
  689. }
  690. ip->i_blocks += (blocksize / 512);
  691. }
  692. return(ip->i_block[blkoff]);
  693. }
  694. /* Is it a single-indirect? */
  695. if(blkoff <= ind1lim) {
  696. iblkno = ip->i_block[EXT2_IND_BLOCK];
  697. if((iblkno == 0) && allocate) {
  698. /* No indirect block and we need one, so we allocate
  699. * one, zero it, and write it out.
  700. */
  701. iblkno = ext2_balloc();
  702. if(iblkno == 0) {
  703. return(0);
  704. }
  705. ip->i_block[EXT2_IND_BLOCK] = iblkno;
  706. if(verbose) {
  707. printf("Allocated indirect block %d\n", iblkno);
  708. }
  709. ip->i_blocks += (blocksize / 512);
  710. memset(blkbuf, 0, blocksize);
  711. bwrite(iblkno, blkbuf);
  712. }
  713. if(iblkno == 0) {
  714. return(0);
  715. }
  716. /* Read the indirect block */
  717. bread(iblkno, blkbuf);
  718. if(big_endian) {
  719. blkno = swap32(lp[blkoff-(directlim+1)]);
  720. }
  721. else {
  722. blkno = lp[blkoff-(directlim+1)];
  723. }
  724. if((blkno == 0) && allocate) {
  725. /* No block allocated but we need one. */
  726. if(big_endian) {
  727. blkno = ext2_balloc();
  728. lp[blkoff-(directlim+1)] = swap32(blkno);
  729. }
  730. else {
  731. blkno = lp[blkoff-(directlim+1)] = ext2_balloc();
  732. }
  733. if(blkno == 0) {
  734. return(0);
  735. }
  736. ip->i_blocks += (blocksize / 512);
  737. if(verbose) {
  738. printf("Allocated data block %d\n", blkno);
  739. }
  740. bwrite(iblkno, blkbuf);
  741. }
  742. return(blkno);
  743. }
  744. /* Is it a double-indirect? */
  745. if(blkoff <= ind2lim) {
  746. /* Find the double-indirect block */
  747. diblkno = ip->i_block[EXT2_DIND_BLOCK];
  748. if((diblkno == 0) && allocate) {
  749. /* No double-indirect block and we need one. Allocate one,
  750. * fill it with zeros, and write it out.
  751. */
  752. diblkno = ext2_balloc();
  753. if(diblkno == 0) {
  754. return(0);
  755. }
  756. ip->i_blocks += (blocksize / 512);
  757. if(verbose) {
  758. printf("Allocated double-indirect block %d\n", diblkno);
  759. }
  760. memset(blkbuf, 0, blocksize);
  761. bwrite(diblkno, blkbuf);
  762. ip->i_block[EXT2_DIND_BLOCK] = diblkno;
  763. }
  764. if(diblkno == 0) {
  765. return(0);
  766. }
  767. /* Read in the double-indirect block */
  768. bread(diblkno, blkbuf);
  769. /* Find the single-indirect block pointer ... */
  770. iblkno = lp[(blkoff - (ind1lim+1)) / ptrs_per_blk];
  771. if(big_endian) {
  772. iblkno = swap32(iblkno);
  773. }
  774. if((iblkno == 0) && allocate) {
  775. /* No indirect block and we need one, so we allocate
  776. * one, zero it, and write it out.
  777. */
  778. iblkno = ext2_balloc();
  779. if(iblkno == 0) {
  780. return(0);
  781. }
  782. ip->i_blocks += (blocksize / 512);
  783. if(verbose) {
  784. printf("Allocated single-indirect block %d\n", iblkno);
  785. }
  786. lp[(blkoff-(ind1lim+1)) / ptrs_per_blk] = big_endian ? swap32(iblkno) : iblkno;
  787. bwrite(diblkno, blkbuf);
  788. memset(blkbuf, 0, blocksize);
  789. bwrite(iblkno, blkbuf);
  790. }
  791. if(iblkno == 0) {
  792. return(0);
  793. }
  794. /* Read the indirect block */
  795. bread(iblkno, blkbuf);
  796. /* Find the block itself. */
  797. blkno = lp[(blkoff-(ind1lim+1)) % ptrs_per_blk];
  798. if(big_endian) {
  799. blkno = swap32(blkno);
  800. }
  801. if((blkno == 0) && allocate) {
  802. /* No block allocated but we need one. */
  803. if(big_endian) {
  804. blkno = ext2_balloc();
  805. lp[(blkoff-(ind1lim+1)) % ptrs_per_blk] = swap32(blkno);
  806. }
  807. else {
  808. blkno = lp[(blkoff-(ind1lim+1)) % ptrs_per_blk] = ext2_balloc();
  809. }
  810. ip->i_blocks += (blocksize / 512);
  811. if(verbose) {
  812. printf("Allocated data block %d\n", blkno);
  813. }
  814. bwrite(iblkno, blkbuf);
  815. }
  816. return(blkno);
  817. }
  818. if(blkoff > ind2lim) {
  819. fprintf(stderr, "ext2_blkno: block number too large: %d\n", blkoff);
  820. return(0);
  821. }
  822. return 0;
  823. }
  824. /* Read block number "blkno" from the specified file */
  825. void
  826. ext2_bread (struct ext2_inode *ip, int blkno, char * buffer)
  827. {
  828. int dev_blkno;
  829. dev_blkno = ext2_blkno(ip, blkno, 0);
  830. if(dev_blkno == 0) {
  831. /* This is a "hole" */
  832. memset(buffer, 0, blocksize);
  833. }
  834. else {
  835. /* Read it for real */
  836. bread(dev_blkno, buffer);
  837. }
  838. }
  839. /* Write block number "blkno" to the specified file */
  840. void
  841. ext2_bwrite (struct ext2_inode *ip, int blkno, char * buffer)
  842. {
  843. int dev_blkno;
  844. if(readonly) {
  845. fprintf(stderr, "ext2_bwrite: Cannot write to a readonly filesystem!\n");
  846. return;
  847. }
  848. dev_blkno = ext2_blkno(ip, blkno, 1);
  849. if(dev_blkno == 0) {
  850. fprintf(stderr, "%s: No space on ext2 device\n", filename);
  851. }
  852. else {
  853. /* Write it for real */
  854. bwrite(dev_blkno, buffer);
  855. }
  856. }
  857. /* More convenient forms of ext2_bread/ext2_bwrite. These allow arbitrary
  858. * data alignment and buffer sizes...
  859. */
  860. int
  861. ext2_seek_and_read (struct ext2_inode *ip, int offset, char *buffer, int count)
  862. {
  863. int blkno;
  864. int blkoffset;
  865. int bytesleft;
  866. int nread;
  867. int iosize;
  868. char *bufptr;
  869. char blkbuf[EXT2_MAX_BLOCK_SIZE];
  870. bufptr = buffer;
  871. bytesleft = count;
  872. nread = 0;
  873. blkno = offset / blocksize;
  874. blkoffset = offset % blocksize;
  875. while(bytesleft > 0) {
  876. iosize = ((blocksize-blkoffset) > bytesleft) ?
  877. bytesleft : (blocksize-blkoffset);
  878. if((blkoffset == 0) && (iosize == blocksize)) {
  879. ext2_bread(ip, blkno, bufptr);
  880. }
  881. else {
  882. ext2_bread(ip, blkno, blkbuf);
  883. memcpy(bufptr, blkbuf+blkoffset, iosize);
  884. }
  885. bytesleft -= iosize;
  886. bufptr += iosize;
  887. nread += iosize;
  888. blkno++;
  889. blkoffset = 0;
  890. }
  891. return(nread);
  892. }
  893. int
  894. ext2_seek_and_write (struct ext2_inode *ip, int offset, char *buffer, int count)
  895. {
  896. int blkno;
  897. int blkoffset;
  898. int bytesleft;
  899. int nwritten;
  900. int iosize;
  901. char *bufptr;
  902. char blkbuf[EXT2_MAX_BLOCK_SIZE];
  903. bufptr = buffer;
  904. bytesleft = count;
  905. nwritten = 0;
  906. blkno = offset / blocksize;
  907. blkoffset = offset % blocksize;
  908. while(bytesleft > 0) {
  909. iosize = ((blocksize-blkoffset) > bytesleft) ?
  910. bytesleft : (blocksize-blkoffset);
  911. if((blkoffset == 0) && (iosize == blocksize)) {
  912. ext2_bwrite(ip, blkno, bufptr);
  913. }
  914. else {
  915. ext2_bread(ip, blkno, blkbuf);
  916. memcpy(blkbuf+blkoffset, bufptr, iosize);
  917. ext2_bwrite(ip, blkno, blkbuf);
  918. }
  919. bytesleft -= iosize;
  920. bufptr += iosize;
  921. nwritten += iosize;
  922. blkno++;
  923. blkoffset = 0;
  924. }
  925. return(nwritten);
  926. }
  927. struct ext2_inode *
  928. ext2_namei (char *name)
  929. {
  930. char namebuf[256];
  931. char dirbuf[EXT2_MAX_BLOCK_SIZE];
  932. char * component;
  933. struct ext2_inode * dir_inode;
  934. struct ext2_dir_entry *dp;
  935. int next_ino;
  936. /* Squirrel away a copy of "namebuf" that we can molest */
  937. strcpy(namebuf, name);
  938. /* Start at the root... */
  939. dir_inode = ext2_iget(EXT2_ROOT_INO);
  940. component = strtok(namebuf, "/");
  941. while(component) {
  942. unsigned diroffset;
  943. int component_length, blockoffset;
  944. /* Search for the specified component in the current directory
  945. * inode.
  946. */
  947. next_ino = -1;
  948. component_length = strlen(component);
  949. diroffset = 0;
  950. while (diroffset < dir_inode->i_size) {
  951. blockoffset = 0;
  952. ext2_bread(dir_inode, diroffset / blocksize, dirbuf);
  953. while (blockoffset < blocksize) {
  954. int namelen;
  955. dp = (struct ext2_dir_entry *)(dirbuf+blockoffset);
  956. namelen = big_endian ? swap16(dp->name_len) : dp->name_len;
  957. if((namelen == component_length) &&
  958. (strncmp(component, dp->name, component_length) == 0)) {
  959. /* Found it! */
  960. next_ino = big_endian ? swap32(dp->inode) : dp->inode;
  961. break;
  962. }
  963. /* Go to next entry in this block */
  964. blockoffset += (big_endian ? swap16(dp->rec_len) : dp->rec_len);
  965. }
  966. if(next_ino >= 0) {
  967. break;
  968. }
  969. /* If we got here, then we didn't find the component.
  970. * Try the next block in this directory...
  971. */
  972. diroffset += blocksize;
  973. }
  974. /* At this point, we're done with this directory whether
  975. * we've succeeded or failed...
  976. */
  977. ext2_iput(dir_inode);
  978. /* If next_ino is negative, then we've failed (gone all the
  979. * way through without finding anything)
  980. */
  981. if(next_ino < 0) {
  982. return(NULL);
  983. }
  984. /* Otherwise, we can get this inode and find the next
  985. * component string...
  986. */
  987. dir_inode = ext2_iget(next_ino);
  988. component = strtok(NULL, "/");
  989. }
  990. /* If we get here, then we got through all the components.
  991. * Whatever we got must match up with the last one.
  992. */
  993. return(dir_inode);
  994. }
  995. /* Create a new entry in the specified directory with the specified
  996. * name/inumber pair. This routine ASSUMES that the specified
  997. * entry does not already exist! Therefore, we MUST use namei
  998. * first to try and find the entry...
  999. */
  1000. void
  1001. ext2_mknod (struct ext2_inode *dip, char * name, int ino)
  1002. {
  1003. unsigned diroffset;
  1004. int blockoffset, namelen, new_reclen;
  1005. struct ext2_dir_entry *dp;
  1006. struct ext2_dir_entry *entry_dp;
  1007. char dirbuf[EXT2_MAX_BLOCK_SIZE];
  1008. int dp_inode, dp_reclen, dp_namelen;
  1009. namelen = strlen(name);
  1010. /* Look for an empty directory entry that can hold this
  1011. * item.
  1012. */
  1013. diroffset = 0;
  1014. entry_dp = NULL;
  1015. while (diroffset < dip->i_size) {
  1016. blockoffset = 0;
  1017. ext2_bread(dip, diroffset / blocksize, dirbuf);
  1018. while(blockoffset < blocksize) {
  1019. dp = (struct ext2_dir_entry *)(dirbuf+blockoffset);
  1020. dp_inode = big_endian ? swap32(dp->inode) : dp->inode;
  1021. dp_reclen = big_endian ? swap16(dp->rec_len) : dp->rec_len;
  1022. dp_namelen = big_endian ? swap16(dp->name_len) : dp->name_len;
  1023. if((dp_inode == 0) && (dp_reclen >= EXT2_DIR_REC_LEN(namelen))) {
  1024. /* Found an *empty* entry that can hold this name. */
  1025. entry_dp = dp;
  1026. break;
  1027. }
  1028. /* If this entry is in use, see if it has space at the end
  1029. * to hold the new entry anyway...
  1030. */
  1031. if((dp_inode != 0) &&
  1032. ((dp_reclen - EXT2_DIR_REC_LEN(dp_namelen))
  1033. >= EXT2_DIR_REC_LEN(namelen))) {
  1034. new_reclen = dp_reclen - EXT2_DIR_REC_LEN(dp_namelen);
  1035. /* Chop the in-use entry down to size */
  1036. if(big_endian) {
  1037. dp_reclen = EXT2_DIR_REC_LEN(swap16(dp->name_len));
  1038. }
  1039. else {
  1040. dp_reclen = EXT2_DIR_REC_LEN(dp->name_len);
  1041. }
  1042. dp->rec_len = big_endian ? swap16(dp_reclen) : dp_reclen;
  1043. /* Point entry_dp to the end of this entry */
  1044. entry_dp = (struct ext2_dir_entry *)((char*)dp + dp_reclen);
  1045. /* Set the record length for this entry */
  1046. entry_dp->rec_len = big_endian ? swap16(new_reclen) : new_reclen;
  1047. /* all set! */
  1048. break;
  1049. }
  1050. /* No luck yet... go to next entry in this block */
  1051. blockoffset += dp_reclen;
  1052. }
  1053. if(entry_dp != NULL) {
  1054. break;
  1055. }
  1056. /* If we got here, then we didn't find the component.
  1057. * Try the next block in this directory...
  1058. */
  1059. diroffset += blocksize;
  1060. }
  1061. /* By the time we get here, one of two things has happened:
  1062. *
  1063. * If entry_dp is non-NULL, then entry_dp points to the
  1064. * place in dirbuf where the entry lives, and diroffset
  1065. * is the directory offset of the beginning of dirbuf.
  1066. *
  1067. * If entry_dp is NULL, then we couldn't find an entry,
  1068. * so we need to add a block to the directory file for
  1069. * this entry...
  1070. */
  1071. if(entry_dp) {
  1072. entry_dp->inode = big_endian ? swap32(ino) : ino;
  1073. entry_dp->name_len = big_endian ? swap16(namelen) : namelen;
  1074. strncpy(entry_dp->name, name, namelen);
  1075. ext2_bwrite(dip, diroffset/blocksize, dirbuf);
  1076. }
  1077. else {
  1078. entry_dp = (struct ext2_dir_entry *)dirbuf;
  1079. entry_dp->inode = big_endian ? swap32(ino) : ino;
  1080. entry_dp->name_len = big_endian ? swap16(namelen) : namelen;
  1081. strncpy(entry_dp->name, name, namelen);
  1082. entry_dp->rec_len = big_endian ? swap16(blocksize) : blocksize;
  1083. ext2_bwrite(dip, dip->i_size/blocksize, dirbuf);
  1084. dip->i_size += blocksize;
  1085. }
  1086. }
  1087. /* This is a close cousin to namei, only it *removes* the entry
  1088. * in addition to finding it. This routine assumes that the specified
  1089. * entry has already been found...
  1090. */
  1091. void
  1092. ext2_remove_entry (char *name)
  1093. {
  1094. char namebuf[256];
  1095. char dirbuf[EXT2_MAX_BLOCK_SIZE];
  1096. char * component;
  1097. struct ext2_inode * dir_inode;
  1098. struct ext2_dir_entry *dp;
  1099. int next_ino;
  1100. int dp_inode, dp_reclen, dp_namelen;
  1101. /* Squirrel away a copy of "namebuf" that we can molest */
  1102. strcpy(namebuf, name);
  1103. /* Start at the root... */
  1104. dir_inode = ext2_iget(EXT2_ROOT_INO);
  1105. component = strtok(namebuf, "/");
  1106. while(component) {
  1107. unsigned diroffset;
  1108. int blockoffset, component_length;
  1109. char *next_component;
  1110. struct ext2_dir_entry * pdp;
  1111. /* Search for the specified component in the current directory
  1112. * inode.
  1113. */
  1114. next_component = NULL;
  1115. pdp = NULL;
  1116. next_ino = -1;
  1117. component_length = strlen(component);
  1118. diroffset = 0;
  1119. while (diroffset < dir_inode->i_size) {
  1120. blockoffset = 0;
  1121. ext2_bread(dir_inode, diroffset / blocksize, dirbuf);
  1122. while(blockoffset < blocksize) {
  1123. dp = (struct ext2_dir_entry *)(dirbuf+blockoffset);
  1124. dp_inode = big_endian ? swap32(dp->inode) : dp->inode;
  1125. dp_reclen = big_endian ? swap16(dp->rec_len) : dp->rec_len;
  1126. dp_namelen = big_endian ? swap16(dp->name_len) : dp->name_len;
  1127. if((dp_namelen == component_length) &&
  1128. (strncmp(component, dp->name, component_length) == 0)) {
  1129. /* Found it! */
  1130. next_component = strtok(NULL, "/");
  1131. if(next_component == NULL) {
  1132. /* We've found the entry that needs to be
  1133. * zapped. If it's at the beginning of the
  1134. * block, then zap it. Otherwise, coalesce
  1135. * it with the previous entry.
  1136. */
  1137. if(pdp) {
  1138. if(big_endian) {
  1139. pdp->rec_len =
  1140. swap16(swap16(pdp->rec_len)+dp_reclen);
  1141. }
  1142. else {
  1143. pdp->rec_len += dp_reclen;
  1144. }
  1145. }
  1146. else {
  1147. dp->inode = 0;
  1148. dp->name_len = 0;
  1149. }
  1150. ext2_bwrite(dir_inode, diroffset / blocksize, dirbuf);
  1151. return;
  1152. }
  1153. next_ino = dp_inode;
  1154. break;
  1155. }
  1156. /* Go to next entry in this block */
  1157. pdp = dp;
  1158. blockoffset += dp_reclen;
  1159. }
  1160. if(next_ino >= 0) {
  1161. break;
  1162. }
  1163. /* If we got here, then we didn't find the component.
  1164. * Try the next block in this directory...
  1165. */
  1166. diroffset += blocksize;
  1167. }
  1168. /* At this point, we're done with this directory whether
  1169. * we've succeeded or failed...
  1170. */
  1171. ext2_iput(dir_inode);
  1172. /* If next_ino is negative, then we've failed (gone all the
  1173. * way through without finding anything)
  1174. */
  1175. if(next_ino < 0) {
  1176. return;
  1177. }
  1178. /* Otherwise, we can get this inode and find the next
  1179. * component string...
  1180. */
  1181. dir_inode = ext2_iget(next_ino);
  1182. component = next_component;
  1183. }
  1184. ext2_iput(dir_inode);
  1185. }
  1186. void
  1187. ext2_truncate (struct ext2_inode *ip)
  1188. {
  1189. int i;
  1190. /* Deallocate all blocks associated with a particular file
  1191. * and set its size to zero.
  1192. */
  1193. /* Direct blocks */
  1194. for(i = 0; i < EXT2_NDIR_BLOCKS; i++) {
  1195. if(ip->i_block[i]) {
  1196. ext2_bfree(ip->i_block[i]);
  1197. ip->i_block[i] = 0;
  1198. }
  1199. }
  1200. /* First-level indirect blocks */
  1201. if(ip->i_block[EXT2_IND_BLOCK]) {
  1202. ext2_free_indirect(ip->i_block[EXT2_IND_BLOCK], 0);
  1203. ip->i_block[EXT2_IND_BLOCK] = 0;
  1204. }
  1205. /* Second-level indirect blocks */
  1206. if(ip->i_block[EXT2_DIND_BLOCK]) {
  1207. ext2_free_indirect(ip->i_block[EXT2_DIND_BLOCK], 1);
  1208. ip->i_block[EXT2_DIND_BLOCK] = 0;
  1209. }
  1210. /* Third-level indirect blocks */
  1211. if(ip->i_block[EXT2_TIND_BLOCK]) {
  1212. ext2_free_indirect(ip->i_block[EXT2_TIND_BLOCK], 2);
  1213. ip->i_block[EXT2_TIND_BLOCK] = 0;
  1214. }
  1215. ip->i_size = 0;
  1216. }
  1217. /* Recursive routine to free an indirect chain */
  1218. static void
  1219. ext2_free_indirect (int indirect_blkno, int level)
  1220. {
  1221. int i, indirect_block[EXT2_MAX_BLOCK_SIZE/4];
  1222. /* Read the specified indirect block */
  1223. bread(indirect_blkno, indirect_block);
  1224. for(i = 0; i < ptrs_per_blk; i++) {
  1225. if(level == 0) {
  1226. /* These are pointers to data blocks; just free them up */
  1227. if(indirect_block[i]) {
  1228. if(big_endian) {
  1229. ext2_bfree(swap32(indirect_block[i]));
  1230. }
  1231. else {
  1232. ext2_bfree(indirect_block[i]);
  1233. }
  1234. indirect_block[i] = 0;
  1235. }
  1236. }
  1237. else {
  1238. /* These are pointers to *indirect* blocks. Go down the chain */
  1239. if(indirect_block[i]) {
  1240. if(big_endian) {
  1241. ext2_free_indirect(swap32(indirect_block[i]), level-1);
  1242. }
  1243. else {
  1244. ext2_free_indirect(indirect_block[i], level-1);
  1245. }
  1246. indirect_block[i] = 0;
  1247. }
  1248. }
  1249. }
  1250. ext2_bfree(indirect_blkno);
  1251. }
  1252. int
  1253. ext2_get_inumber (struct ext2_inode *ip)
  1254. {
  1255. struct inode_table_entry *itp;
  1256. itp = (struct inode_table_entry *)ip;
  1257. return(itp->inumber);
  1258. }