dir.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /*
  2. * linux/fs/ufs/ufs_dir.c
  3. *
  4. * Copyright (C) 1996
  5. * Adrian Rodriguez (adrian@franklins-tower.rutgers.edu)
  6. * Laboratory for Computer Science Research Computing Facility
  7. * Rutgers, The State University of New Jersey
  8. *
  9. * swab support by Francois-Rene Rideau <fare@tunes.org> 19970406
  10. *
  11. * 4.4BSD (FreeBSD) support added on February 1st 1998 by
  12. * Niels Kristian Bech Jensen <nkbj@image.dk> partially based
  13. * on code by Martin von Loewis <martin@mira.isdn.cs.tu-berlin.de>.
  14. */
  15. #include <linux/time.h>
  16. #include <linux/fs.h>
  17. #include <linux/ufs_fs.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/buffer_head.h>
  20. #include <linux/sched.h>
  21. #include "swab.h"
  22. #include "util.h"
  23. #undef UFS_DIR_DEBUG
  24. #ifdef UFS_DIR_DEBUG
  25. #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
  26. #else
  27. #define UFSD(x)
  28. #endif
  29. static int
  30. ufs_check_dir_entry (const char *, struct inode *, struct ufs_dir_entry *,
  31. struct buffer_head *, unsigned long);
  32. /*
  33. * NOTE! unlike strncmp, ufs_match returns 1 for success, 0 for failure.
  34. *
  35. * len <= UFS_MAXNAMLEN and de != NULL are guaranteed by caller.
  36. */
  37. static inline int ufs_match(struct super_block *sb, int len,
  38. const char * const name, struct ufs_dir_entry * de)
  39. {
  40. if (len != ufs_get_de_namlen(sb, de))
  41. return 0;
  42. if (!de->d_ino)
  43. return 0;
  44. return !memcmp(name, de->d_name, len);
  45. }
  46. /*
  47. * This is blatantly stolen from ext2fs
  48. */
  49. static int
  50. ufs_readdir (struct file * filp, void * dirent, filldir_t filldir)
  51. {
  52. struct inode *inode = filp->f_dentry->d_inode;
  53. int error = 0;
  54. unsigned long offset, lblk;
  55. int i, stored;
  56. struct buffer_head * bh;
  57. struct ufs_dir_entry * de;
  58. struct super_block * sb;
  59. int de_reclen;
  60. unsigned flags;
  61. u64 blk= 0L;
  62. lock_kernel();
  63. sb = inode->i_sb;
  64. flags = UFS_SB(sb)->s_flags;
  65. UFSD(("ENTER, ino %lu f_pos %lu\n", inode->i_ino, (unsigned long) filp->f_pos))
  66. stored = 0;
  67. bh = NULL;
  68. offset = filp->f_pos & (sb->s_blocksize - 1);
  69. while (!error && !stored && filp->f_pos < inode->i_size) {
  70. lblk = (filp->f_pos) >> sb->s_blocksize_bits;
  71. blk = ufs_frag_map(inode, lblk);
  72. if (!blk || !(bh = sb_bread(sb, blk))) {
  73. /* XXX - error - skip to the next block */
  74. printk("ufs_readdir: "
  75. "dir inode %lu has a hole at offset %lu\n",
  76. inode->i_ino, (unsigned long int)filp->f_pos);
  77. filp->f_pos += sb->s_blocksize - offset;
  78. continue;
  79. }
  80. revalidate:
  81. /* If the dir block has changed since the last call to
  82. * readdir(2), then we might be pointing to an invalid
  83. * dirent right now. Scan from the start of the block
  84. * to make sure. */
  85. if (filp->f_version != inode->i_version) {
  86. for (i = 0; i < sb->s_blocksize && i < offset; ) {
  87. de = (struct ufs_dir_entry *)(bh->b_data + i);
  88. /* It's too expensive to do a full
  89. * dirent test each time round this
  90. * loop, but we do have to test at
  91. * least that it is non-zero. A
  92. * failure will be detected in the
  93. * dirent test below. */
  94. de_reclen = fs16_to_cpu(sb, de->d_reclen);
  95. if (de_reclen < 1)
  96. break;
  97. i += de_reclen;
  98. }
  99. offset = i;
  100. filp->f_pos = (filp->f_pos & ~(sb->s_blocksize - 1))
  101. | offset;
  102. filp->f_version = inode->i_version;
  103. }
  104. while (!error && filp->f_pos < inode->i_size
  105. && offset < sb->s_blocksize) {
  106. de = (struct ufs_dir_entry *) (bh->b_data + offset);
  107. /* XXX - put in a real ufs_check_dir_entry() */
  108. if ((de->d_reclen == 0) || (ufs_get_de_namlen(sb, de) == 0)) {
  109. filp->f_pos = (filp->f_pos &
  110. (sb->s_blocksize - 1)) +
  111. sb->s_blocksize;
  112. brelse(bh);
  113. unlock_kernel();
  114. return stored;
  115. }
  116. if (!ufs_check_dir_entry ("ufs_readdir", inode, de,
  117. bh, offset)) {
  118. /* On error, skip the f_pos to the
  119. next block. */
  120. filp->f_pos = (filp->f_pos |
  121. (sb->s_blocksize - 1)) +
  122. 1;
  123. brelse (bh);
  124. unlock_kernel();
  125. return stored;
  126. }
  127. offset += fs16_to_cpu(sb, de->d_reclen);
  128. if (de->d_ino) {
  129. /* We might block in the next section
  130. * if the data destination is
  131. * currently swapped out. So, use a
  132. * version stamp to detect whether or
  133. * not the directory has been modified
  134. * during the copy operation. */
  135. unsigned long version = filp->f_version;
  136. unsigned char d_type = DT_UNKNOWN;
  137. UFSD(("filldir(%s,%u)\n", de->d_name,
  138. fs32_to_cpu(sb, de->d_ino)))
  139. UFSD(("namlen %u\n", ufs_get_de_namlen(sb, de)))
  140. if ((flags & UFS_DE_MASK) == UFS_DE_44BSD)
  141. d_type = de->d_u.d_44.d_type;
  142. error = filldir(dirent, de->d_name,
  143. ufs_get_de_namlen(sb, de), filp->f_pos,
  144. fs32_to_cpu(sb, de->d_ino), d_type);
  145. if (error)
  146. break;
  147. if (version != filp->f_version)
  148. goto revalidate;
  149. stored ++;
  150. }
  151. filp->f_pos += fs16_to_cpu(sb, de->d_reclen);
  152. }
  153. offset = 0;
  154. brelse (bh);
  155. }
  156. unlock_kernel();
  157. return 0;
  158. }
  159. /*
  160. * define how far ahead to read directories while searching them.
  161. */
  162. #define NAMEI_RA_CHUNKS 2
  163. #define NAMEI_RA_BLOCKS 4
  164. #define NAMEI_RA_SIZE (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
  165. #define NAMEI_RA_INDEX(c,b) (((c) * NAMEI_RA_BLOCKS) + (b))
  166. /*
  167. * ufs_find_entry()
  168. *
  169. * finds an entry in the specified directory with the wanted name. It
  170. * returns the cache buffer in which the entry was found, and the entry
  171. * itself (as a parameter - res_bh). It does NOT read the inode of the
  172. * entry - you'll have to do that yourself if you want to.
  173. */
  174. struct ufs_dir_entry * ufs_find_entry (struct dentry *dentry,
  175. struct buffer_head ** res_bh)
  176. {
  177. struct super_block * sb;
  178. struct buffer_head * bh_use[NAMEI_RA_SIZE];
  179. struct buffer_head * bh_read[NAMEI_RA_SIZE];
  180. unsigned long offset;
  181. int block, toread, i, err;
  182. struct inode *dir = dentry->d_parent->d_inode;
  183. const char *name = dentry->d_name.name;
  184. int namelen = dentry->d_name.len;
  185. UFSD(("ENTER, dir_ino %lu, name %s, namlen %u\n", dir->i_ino, name, namelen))
  186. *res_bh = NULL;
  187. sb = dir->i_sb;
  188. if (namelen > UFS_MAXNAMLEN)
  189. return NULL;
  190. memset (bh_use, 0, sizeof (bh_use));
  191. toread = 0;
  192. for (block = 0; block < NAMEI_RA_SIZE; ++block) {
  193. struct buffer_head * bh;
  194. if ((block << sb->s_blocksize_bits) >= dir->i_size)
  195. break;
  196. bh = ufs_getfrag (dir, block, 0, &err);
  197. bh_use[block] = bh;
  198. if (bh && !buffer_uptodate(bh))
  199. bh_read[toread++] = bh;
  200. }
  201. for (block = 0, offset = 0; offset < dir->i_size; block++) {
  202. struct buffer_head * bh;
  203. struct ufs_dir_entry * de;
  204. char * dlimit;
  205. if ((block % NAMEI_RA_BLOCKS) == 0 && toread) {
  206. ll_rw_block (READ, toread, bh_read);
  207. toread = 0;
  208. }
  209. bh = bh_use[block % NAMEI_RA_SIZE];
  210. if (!bh) {
  211. ufs_error (sb, "ufs_find_entry",
  212. "directory #%lu contains a hole at offset %lu",
  213. dir->i_ino, offset);
  214. offset += sb->s_blocksize;
  215. continue;
  216. }
  217. wait_on_buffer (bh);
  218. if (!buffer_uptodate(bh)) {
  219. /*
  220. * read error: all bets are off
  221. */
  222. break;
  223. }
  224. de = (struct ufs_dir_entry *) bh->b_data;
  225. dlimit = bh->b_data + sb->s_blocksize;
  226. while ((char *) de < dlimit && offset < dir->i_size) {
  227. /* this code is executed quadratically often */
  228. /* do minimal checking by hand */
  229. int de_len;
  230. if ((char *) de + namelen <= dlimit &&
  231. ufs_match(sb, namelen, name, de)) {
  232. /* found a match -
  233. just to be sure, do a full check */
  234. if (!ufs_check_dir_entry("ufs_find_entry",
  235. dir, de, bh, offset))
  236. goto failed;
  237. for (i = 0; i < NAMEI_RA_SIZE; ++i) {
  238. if (bh_use[i] != bh)
  239. brelse (bh_use[i]);
  240. }
  241. *res_bh = bh;
  242. return de;
  243. }
  244. /* prevent looping on a bad block */
  245. de_len = fs16_to_cpu(sb, de->d_reclen);
  246. if (de_len <= 0)
  247. goto failed;
  248. offset += de_len;
  249. de = (struct ufs_dir_entry *) ((char *) de + de_len);
  250. }
  251. brelse (bh);
  252. if (((block + NAMEI_RA_SIZE) << sb->s_blocksize_bits ) >=
  253. dir->i_size)
  254. bh = NULL;
  255. else
  256. bh = ufs_getfrag (dir, block + NAMEI_RA_SIZE, 0, &err);
  257. bh_use[block % NAMEI_RA_SIZE] = bh;
  258. if (bh && !buffer_uptodate(bh))
  259. bh_read[toread++] = bh;
  260. }
  261. failed:
  262. for (i = 0; i < NAMEI_RA_SIZE; ++i) brelse (bh_use[i]);
  263. UFSD(("EXIT\n"))
  264. return NULL;
  265. }
  266. static int
  267. ufs_check_dir_entry (const char *function, struct inode *dir,
  268. struct ufs_dir_entry *de, struct buffer_head *bh,
  269. unsigned long offset)
  270. {
  271. struct super_block *sb = dir->i_sb;
  272. const char *error_msg = NULL;
  273. int rlen = fs16_to_cpu(sb, de->d_reclen);
  274. if (rlen < UFS_DIR_REC_LEN(1))
  275. error_msg = "reclen is smaller than minimal";
  276. else if (rlen % 4 != 0)
  277. error_msg = "reclen % 4 != 0";
  278. else if (rlen < UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)))
  279. error_msg = "reclen is too small for namlen";
  280. else if (((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize)
  281. error_msg = "directory entry across blocks";
  282. else if (fs32_to_cpu(sb, de->d_ino) > (UFS_SB(sb)->s_uspi->s_ipg *
  283. UFS_SB(sb)->s_uspi->s_ncg))
  284. error_msg = "inode out of bounds";
  285. if (error_msg != NULL)
  286. ufs_error (sb, function, "bad entry in directory #%lu, size %Lu: %s - "
  287. "offset=%lu, inode=%lu, reclen=%d, namlen=%d",
  288. dir->i_ino, dir->i_size, error_msg, offset,
  289. (unsigned long)fs32_to_cpu(sb, de->d_ino),
  290. rlen, ufs_get_de_namlen(sb, de));
  291. return (error_msg == NULL ? 1 : 0);
  292. }
  293. struct ufs_dir_entry *ufs_dotdot(struct inode *dir, struct buffer_head **p)
  294. {
  295. int err;
  296. struct buffer_head *bh = ufs_bread (dir, 0, 0, &err);
  297. struct ufs_dir_entry *res = NULL;
  298. if (bh) {
  299. res = (struct ufs_dir_entry *) bh->b_data;
  300. res = (struct ufs_dir_entry *)((char *)res +
  301. fs16_to_cpu(dir->i_sb, res->d_reclen));
  302. }
  303. *p = bh;
  304. return res;
  305. }
  306. ino_t ufs_inode_by_name(struct inode * dir, struct dentry *dentry)
  307. {
  308. ino_t res = 0;
  309. struct ufs_dir_entry * de;
  310. struct buffer_head *bh;
  311. de = ufs_find_entry (dentry, &bh);
  312. if (de) {
  313. res = fs32_to_cpu(dir->i_sb, de->d_ino);
  314. brelse(bh);
  315. }
  316. return res;
  317. }
  318. void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de,
  319. struct buffer_head *bh, struct inode *inode)
  320. {
  321. dir->i_version++;
  322. de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino);
  323. mark_buffer_dirty(bh);
  324. if (IS_DIRSYNC(dir))
  325. sync_dirty_buffer(bh);
  326. brelse (bh);
  327. }
  328. /*
  329. * ufs_add_entry()
  330. *
  331. * adds a file entry to the specified directory, using the same
  332. * semantics as ufs_find_entry(). It returns NULL if it failed.
  333. */
  334. int ufs_add_link(struct dentry *dentry, struct inode *inode)
  335. {
  336. struct super_block * sb;
  337. struct ufs_sb_private_info * uspi;
  338. unsigned long offset;
  339. unsigned fragoff;
  340. unsigned short rec_len;
  341. struct buffer_head * bh;
  342. struct ufs_dir_entry * de, * de1;
  343. struct inode *dir = dentry->d_parent->d_inode;
  344. const char *name = dentry->d_name.name;
  345. int namelen = dentry->d_name.len;
  346. int err;
  347. UFSD(("ENTER, name %s, namelen %u\n", name, namelen))
  348. sb = dir->i_sb;
  349. uspi = UFS_SB(sb)->s_uspi;
  350. if (!namelen)
  351. return -EINVAL;
  352. bh = ufs_bread (dir, 0, 0, &err);
  353. if (!bh)
  354. return err;
  355. rec_len = UFS_DIR_REC_LEN(namelen);
  356. offset = 0;
  357. de = (struct ufs_dir_entry *) bh->b_data;
  358. while (1) {
  359. if ((char *)de >= UFS_SECTOR_SIZE + bh->b_data) {
  360. fragoff = offset & ~uspi->s_fmask;
  361. if (fragoff != 0 && fragoff != UFS_SECTOR_SIZE)
  362. ufs_error (sb, "ufs_add_entry", "internal error"
  363. " fragoff %u", fragoff);
  364. if (!fragoff) {
  365. brelse (bh);
  366. bh = ufs_bread (dir, offset >> sb->s_blocksize_bits, 1, &err);
  367. if (!bh)
  368. return err;
  369. }
  370. if (dir->i_size <= offset) {
  371. if (dir->i_size == 0) {
  372. brelse(bh);
  373. return -ENOENT;
  374. }
  375. de = (struct ufs_dir_entry *) (bh->b_data + fragoff);
  376. de->d_ino = 0;
  377. de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE);
  378. ufs_set_de_namlen(sb, de, 0);
  379. dir->i_size = offset + UFS_SECTOR_SIZE;
  380. mark_inode_dirty(dir);
  381. } else {
  382. de = (struct ufs_dir_entry *) bh->b_data;
  383. }
  384. }
  385. if (!ufs_check_dir_entry ("ufs_add_entry", dir, de, bh, offset)) {
  386. brelse (bh);
  387. return -ENOENT;
  388. }
  389. if (ufs_match(sb, namelen, name, de)) {
  390. brelse (bh);
  391. return -EEXIST;
  392. }
  393. if (de->d_ino == 0 && fs16_to_cpu(sb, de->d_reclen) >= rec_len)
  394. break;
  395. if (fs16_to_cpu(sb, de->d_reclen) >=
  396. UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)) + rec_len)
  397. break;
  398. offset += fs16_to_cpu(sb, de->d_reclen);
  399. de = (struct ufs_dir_entry *) ((char *) de + fs16_to_cpu(sb, de->d_reclen));
  400. }
  401. if (de->d_ino) {
  402. de1 = (struct ufs_dir_entry *) ((char *) de +
  403. UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  404. de1->d_reclen =
  405. cpu_to_fs16(sb, fs16_to_cpu(sb, de->d_reclen) -
  406. UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  407. de->d_reclen =
  408. cpu_to_fs16(sb, UFS_DIR_REC_LEN(ufs_get_de_namlen(sb, de)));
  409. de = de1;
  410. }
  411. de->d_ino = 0;
  412. ufs_set_de_namlen(sb, de, namelen);
  413. memcpy (de->d_name, name, namelen + 1);
  414. de->d_ino = cpu_to_fs32(sb, inode->i_ino);
  415. ufs_set_de_type(sb, de, inode->i_mode);
  416. mark_buffer_dirty(bh);
  417. if (IS_DIRSYNC(dir))
  418. sync_dirty_buffer(bh);
  419. brelse (bh);
  420. dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC;
  421. dir->i_version++;
  422. mark_inode_dirty(dir);
  423. UFSD(("EXIT\n"))
  424. return 0;
  425. }
  426. /*
  427. * ufs_delete_entry deletes a directory entry by merging it with the
  428. * previous entry.
  429. */
  430. int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir,
  431. struct buffer_head * bh )
  432. {
  433. struct super_block * sb;
  434. struct ufs_dir_entry * de, * pde;
  435. unsigned i;
  436. UFSD(("ENTER\n"))
  437. sb = inode->i_sb;
  438. i = 0;
  439. pde = NULL;
  440. de = (struct ufs_dir_entry *) bh->b_data;
  441. UFSD(("ino %u, reclen %u, namlen %u, name %s\n",
  442. fs32_to_cpu(sb, de->d_ino),
  443. fs16_to_cpu(sb, de->d_reclen),
  444. ufs_get_de_namlen(sb, de), de->d_name))
  445. while (i < bh->b_size) {
  446. if (!ufs_check_dir_entry ("ufs_delete_entry", inode, de, bh, i)) {
  447. brelse(bh);
  448. return -EIO;
  449. }
  450. if (de == dir) {
  451. if (pde)
  452. fs16_add(sb, &pde->d_reclen,
  453. fs16_to_cpu(sb, dir->d_reclen));
  454. dir->d_ino = 0;
  455. inode->i_version++;
  456. inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
  457. mark_inode_dirty(inode);
  458. mark_buffer_dirty(bh);
  459. if (IS_DIRSYNC(inode))
  460. sync_dirty_buffer(bh);
  461. brelse(bh);
  462. UFSD(("EXIT\n"))
  463. return 0;
  464. }
  465. i += fs16_to_cpu(sb, de->d_reclen);
  466. if (i == UFS_SECTOR_SIZE) pde = NULL;
  467. else pde = de;
  468. de = (struct ufs_dir_entry *)
  469. ((char *) de + fs16_to_cpu(sb, de->d_reclen));
  470. if (i == UFS_SECTOR_SIZE && de->d_reclen == 0)
  471. break;
  472. }
  473. UFSD(("EXIT\n"))
  474. brelse(bh);
  475. return -ENOENT;
  476. }
  477. int ufs_make_empty(struct inode * inode, struct inode *dir)
  478. {
  479. struct super_block * sb = dir->i_sb;
  480. struct buffer_head * dir_block;
  481. struct ufs_dir_entry * de;
  482. int err;
  483. dir_block = ufs_bread (inode, 0, 1, &err);
  484. if (!dir_block)
  485. return err;
  486. inode->i_blocks = sb->s_blocksize / UFS_SECTOR_SIZE;
  487. de = (struct ufs_dir_entry *) dir_block->b_data;
  488. de->d_ino = cpu_to_fs32(sb, inode->i_ino);
  489. ufs_set_de_type(sb, de, inode->i_mode);
  490. ufs_set_de_namlen(sb, de, 1);
  491. de->d_reclen = cpu_to_fs16(sb, UFS_DIR_REC_LEN(1));
  492. strcpy (de->d_name, ".");
  493. de = (struct ufs_dir_entry *)
  494. ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  495. de->d_ino = cpu_to_fs32(sb, dir->i_ino);
  496. ufs_set_de_type(sb, de, dir->i_mode);
  497. de->d_reclen = cpu_to_fs16(sb, UFS_SECTOR_SIZE - UFS_DIR_REC_LEN(1));
  498. ufs_set_de_namlen(sb, de, 2);
  499. strcpy (de->d_name, "..");
  500. mark_buffer_dirty(dir_block);
  501. brelse (dir_block);
  502. mark_inode_dirty(inode);
  503. return 0;
  504. }
  505. /*
  506. * routine to check that the specified directory is empty (for rmdir)
  507. */
  508. int ufs_empty_dir (struct inode * inode)
  509. {
  510. struct super_block * sb;
  511. unsigned long offset;
  512. struct buffer_head * bh;
  513. struct ufs_dir_entry * de, * de1;
  514. int err;
  515. sb = inode->i_sb;
  516. if (inode->i_size < UFS_DIR_REC_LEN(1) + UFS_DIR_REC_LEN(2) ||
  517. !(bh = ufs_bread (inode, 0, 0, &err))) {
  518. ufs_warning (inode->i_sb, "empty_dir",
  519. "bad directory (dir #%lu) - no data block",
  520. inode->i_ino);
  521. return 1;
  522. }
  523. de = (struct ufs_dir_entry *) bh->b_data;
  524. de1 = (struct ufs_dir_entry *)
  525. ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  526. if (fs32_to_cpu(sb, de->d_ino) != inode->i_ino || de1->d_ino == 0 ||
  527. strcmp (".", de->d_name) || strcmp ("..", de1->d_name)) {
  528. ufs_warning (inode->i_sb, "empty_dir",
  529. "bad directory (dir #%lu) - no `.' or `..'",
  530. inode->i_ino);
  531. return 1;
  532. }
  533. offset = fs16_to_cpu(sb, de->d_reclen) + fs16_to_cpu(sb, de1->d_reclen);
  534. de = (struct ufs_dir_entry *)
  535. ((char *)de1 + fs16_to_cpu(sb, de1->d_reclen));
  536. while (offset < inode->i_size ) {
  537. if (!bh || (void *) de >= (void *) (bh->b_data + sb->s_blocksize)) {
  538. brelse (bh);
  539. bh = ufs_bread (inode, offset >> sb->s_blocksize_bits, 1, &err);
  540. if (!bh) {
  541. ufs_error (sb, "empty_dir",
  542. "directory #%lu contains a hole at offset %lu",
  543. inode->i_ino, offset);
  544. offset += sb->s_blocksize;
  545. continue;
  546. }
  547. de = (struct ufs_dir_entry *) bh->b_data;
  548. }
  549. if (!ufs_check_dir_entry ("empty_dir", inode, de, bh, offset)) {
  550. brelse (bh);
  551. return 1;
  552. }
  553. if (de->d_ino) {
  554. brelse (bh);
  555. return 0;
  556. }
  557. offset += fs16_to_cpu(sb, de->d_reclen);
  558. de = (struct ufs_dir_entry *)
  559. ((char *)de + fs16_to_cpu(sb, de->d_reclen));
  560. }
  561. brelse (bh);
  562. return 1;
  563. }
  564. const struct file_operations ufs_dir_operations = {
  565. .read = generic_read_dir,
  566. .readdir = ufs_readdir,
  567. .fsync = file_fsync,
  568. };