dir.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:9k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/minix/dir.c
  3.  *
  4.  *  Copyright (C) 1991, 1992 Linus Torvalds
  5.  *
  6.  *  minix directory handling functions
  7.  */
  8. #include <linux/fs.h>
  9. #include <linux/minix_fs.h>
  10. #include <linux/pagemap.h>
  11. typedef struct minix_dir_entry minix_dirent;
  12. static int minix_readdir(struct file *, void *, filldir_t);
  13. struct file_operations minix_dir_operations = {
  14. read: generic_read_dir,
  15. readdir: minix_readdir,
  16. fsync: minix_sync_file,
  17. };
  18. static inline void dir_put_page(struct page *page)
  19. {
  20. kunmap(page);
  21. page_cache_release(page);
  22. }
  23. static inline unsigned long dir_pages(struct inode *inode)
  24. {
  25. return (inode->i_size+PAGE_CACHE_SIZE-1)>>PAGE_CACHE_SHIFT;
  26. }
  27. static int dir_commit_chunk(struct page *page, unsigned from, unsigned to)
  28. {
  29. struct inode *dir = (struct inode *)page->mapping->host;
  30. int err = 0;
  31. page->mapping->a_ops->commit_write(NULL, page, from, to);
  32. if (IS_SYNC(dir)) {
  33. int err2;
  34. err = writeout_one_page(page);
  35. err2 = waitfor_one_page(page);
  36. if (err == 0)
  37. err = err2;
  38. }
  39. return err;
  40. }
  41. static struct page * dir_get_page(struct inode *dir, unsigned long n)
  42. {
  43. struct address_space *mapping = dir->i_mapping;
  44. struct page *page = read_cache_page(mapping, n,
  45. (filler_t*)mapping->a_ops->readpage, NULL);
  46. if (!IS_ERR(page)) {
  47. wait_on_page(page);
  48. kmap(page);
  49. if (!Page_Uptodate(page))
  50. goto fail;
  51. }
  52. return page;
  53. fail:
  54. dir_put_page(page);
  55. return ERR_PTR(-EIO);
  56. }
  57. static inline void *minix_next_entry(void *de, struct minix_sb_info *sbi)
  58. {
  59. return (void*)((char*)de + sbi->s_dirsize);
  60. }
  61. static int minix_readdir(struct file * filp, void * dirent, filldir_t filldir)
  62. {
  63. unsigned long pos = filp->f_pos;
  64. struct inode *inode = filp->f_dentry->d_inode;
  65. struct super_block *sb = inode->i_sb;
  66. unsigned offset = pos & ~PAGE_CACHE_MASK;
  67. unsigned long n = pos >> PAGE_CACHE_SHIFT;
  68. unsigned long npages = dir_pages(inode);
  69. struct minix_sb_info *sbi = &sb->u.minix_sb;
  70. unsigned chunk_size = sbi->s_dirsize;
  71. pos = (pos + chunk_size-1) & ~(chunk_size-1);
  72. if (pos >= inode->i_size)
  73. goto done;
  74. for ( ; n < npages; n++, offset = 0) {
  75. char *p, *kaddr, *limit;
  76. struct page *page = dir_get_page(inode, n);
  77. if (IS_ERR(page))
  78. continue;
  79. kaddr = (char *)page_address(page);
  80. p = kaddr+offset;
  81. limit = kaddr + PAGE_CACHE_SIZE - chunk_size;
  82. for ( ; p <= limit ; p = minix_next_entry(p, sbi)) {
  83. minix_dirent *de = (minix_dirent *)p;
  84. if (de->inode) {
  85. int over;
  86. unsigned l = strnlen(de->name,sbi->s_namelen);
  87. offset = p - kaddr;
  88. over = filldir(dirent, de->name, l,
  89. (n<<PAGE_CACHE_SHIFT) | offset,
  90. de->inode, DT_UNKNOWN);
  91. if (over) {
  92. dir_put_page(page);
  93. goto done;
  94. }
  95. }
  96. }
  97. dir_put_page(page);
  98. }
  99. done:
  100. filp->f_pos = (n << PAGE_CACHE_SHIFT) | offset;
  101. UPDATE_ATIME(inode);
  102. return 0;
  103. }
  104. static inline int namecompare(int len, int maxlen,
  105. const char * name, const char * buffer)
  106. {
  107. if (len < maxlen && buffer[len])
  108. return 0;
  109. return !memcmp(name, buffer, len);
  110. }
  111. /*
  112.  * minix_find_entry()
  113.  *
  114.  * finds an entry in the specified directory with the wanted name. It
  115.  * returns the cache buffer in which the entry was found, and the entry
  116.  * itself (as a parameter - res_dir). It does NOT read the inode of the
  117.  * entry - you'll have to do that yourself if you want to.
  118.  */
  119. minix_dirent *minix_find_entry(struct dentry *dentry, struct page **res_page)
  120. {
  121. const char * name = dentry->d_name.name;
  122. int namelen = dentry->d_name.len;
  123. struct inode * dir = dentry->d_parent->d_inode;
  124. struct super_block * sb = dir->i_sb;
  125. struct minix_sb_info * sbi = &sb->u.minix_sb;
  126. unsigned long n;
  127. unsigned long npages = dir_pages(dir);
  128. struct page *page = NULL;
  129. struct minix_dir_entry *de;
  130. *res_page = NULL;
  131. for (n = 0; n < npages; n++) {
  132. char *kaddr;
  133. page = dir_get_page(dir, n);
  134. if (IS_ERR(page))
  135. continue;
  136. kaddr = (char*)page_address(page);
  137. de = (struct minix_dir_entry *) kaddr;
  138. kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
  139. for ( ; (char *) de <= kaddr ; de = minix_next_entry(de,sbi)) {
  140. if (!de->inode)
  141. continue;
  142. if (namecompare(namelen,sbi->s_namelen,name,de->name))
  143. goto found;
  144. }
  145. dir_put_page(page);
  146. }
  147. return NULL;
  148. found:
  149. *res_page = page;
  150. return de;
  151. }
  152. int minix_add_link(struct dentry *dentry, struct inode *inode)
  153. {
  154. struct inode *dir = dentry->d_parent->d_inode;
  155. const char * name = dentry->d_name.name;
  156. int namelen = dentry->d_name.len;
  157. struct super_block * sb = dir->i_sb;
  158. struct minix_sb_info * sbi = &sb->u.minix_sb;
  159. struct page *page = NULL;
  160. struct minix_dir_entry * de;
  161. unsigned long npages = dir_pages(dir);
  162. unsigned long n;
  163. char *kaddr;
  164. unsigned from, to;
  165. int err;
  166. /* We take care of directory expansion in the same loop */
  167. for (n = 0; n <= npages; n++) {
  168. page = dir_get_page(dir, n);
  169. err = PTR_ERR(page);
  170. if (IS_ERR(page))
  171. goto out;
  172. kaddr = (char*)page_address(page);
  173. de = (minix_dirent *)kaddr;
  174. kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
  175. while ((char *)de <= kaddr) {
  176. if (!de->inode)
  177. goto got_it;
  178. err = -EEXIST;
  179. if (namecompare(namelen,sbi->s_namelen,name,de->name))
  180. goto out_page;
  181. de = minix_next_entry(de, sbi);
  182. }
  183. dir_put_page(page);
  184. }
  185. BUG();
  186. return -EINVAL;
  187. got_it:
  188. from = (char*)de - (char*)page_address(page);
  189. to = from + sbi->s_dirsize;
  190. lock_page(page);
  191. err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
  192. if (err)
  193. goto out_unlock;
  194. memcpy (de->name, name, namelen);
  195. memset (de->name + namelen, 0, sbi->s_dirsize - namelen - 2);
  196. de->inode = inode->i_ino;
  197. err = dir_commit_chunk(page, from, to);
  198. dir->i_mtime = dir->i_ctime = CURRENT_TIME;
  199. mark_inode_dirty(dir);
  200. out_unlock:
  201. UnlockPage(page);
  202. out_page:
  203. dir_put_page(page);
  204. out:
  205. return err;
  206. }
  207. int minix_delete_entry(struct minix_dir_entry *de, struct page *page)
  208. {
  209. struct address_space *mapping = page->mapping;
  210. struct inode *inode = (struct inode*)mapping->host;
  211. char *kaddr = (char*)page_address(page);
  212. unsigned from = (char*)de - kaddr;
  213. unsigned to = from + inode->i_sb->u.minix_sb.s_dirsize;
  214. int err;
  215. lock_page(page);
  216. err = mapping->a_ops->prepare_write(NULL, page, from, to);
  217. if (err == 0) {
  218. de->inode = 0;
  219. err = dir_commit_chunk(page, from, to);
  220. }
  221. UnlockPage(page);
  222. dir_put_page(page);
  223. inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  224. mark_inode_dirty(inode);
  225. return err;
  226. }
  227. int minix_make_empty(struct inode *inode, struct inode *dir)
  228. {
  229. struct address_space *mapping = inode->i_mapping;
  230. struct page *page = grab_cache_page(mapping, 0);
  231. struct minix_sb_info * sbi = &inode->i_sb->u.minix_sb;
  232. struct minix_dir_entry * de;
  233. char *base;
  234. int err;
  235. if (!page)
  236. return -ENOMEM;
  237. err = mapping->a_ops->prepare_write(NULL, page, 0, 2 * sbi->s_dirsize);
  238. if (err)
  239. goto fail;
  240. base = (char*)page_address(page);
  241. memset(base, 0, PAGE_CACHE_SIZE);
  242. de = (struct minix_dir_entry *) base;
  243. de->inode = inode->i_ino;
  244. strcpy(de->name,".");
  245. de = minix_next_entry(de, sbi);
  246. de->inode = dir->i_ino;
  247. strcpy(de->name,"..");
  248. err = dir_commit_chunk(page, 0, 2 * sbi->s_dirsize);
  249. fail:
  250. UnlockPage(page);
  251. page_cache_release(page);
  252. return err;
  253. }
  254. /*
  255.  * routine to check that the specified directory is empty (for rmdir)
  256.  */
  257. int minix_empty_dir(struct inode * inode)
  258. {
  259. struct page *page = NULL;
  260. unsigned long i, npages = dir_pages(inode);
  261. struct minix_sb_info *sbi = &inode->i_sb->u.minix_sb;
  262. for (i = 0; i < npages; i++) {
  263. char *kaddr;
  264. minix_dirent * de;
  265. page = dir_get_page(inode, i);
  266. if (IS_ERR(page))
  267. continue;
  268. kaddr = (char *)page_address(page);
  269. de = (minix_dirent *)kaddr;
  270. kaddr += PAGE_CACHE_SIZE - sbi->s_dirsize;
  271. while ((char *)de <= kaddr) {
  272. if (de->inode != 0) {
  273. /* check for . and .. */
  274. if (de->name[0] != '.')
  275. goto not_empty;
  276. if (!de->name[1]) {
  277. if (de->inode != inode->i_ino)
  278. goto not_empty;
  279. } else if (de->name[1] != '.')
  280. goto not_empty;
  281. else if (de->name[2])
  282. goto not_empty;
  283. }
  284. de = minix_next_entry(de, sbi);
  285. }
  286. dir_put_page(page);
  287. }
  288. return 1;
  289. not_empty:
  290. dir_put_page(page);
  291. return 0;
  292. }
  293. /* Releases the page */
  294. void minix_set_link(struct minix_dir_entry *de, struct page *page,
  295. struct inode *inode)
  296. {
  297. struct inode *dir = (struct inode*)page->mapping->host;
  298. struct minix_sb_info *sbi = &dir->i_sb->u.minix_sb;
  299. unsigned from = (char *)de-(char*)page_address(page);
  300. unsigned to = from + sbi->s_dirsize;
  301. int err;
  302. lock_page(page);
  303. err = page->mapping->a_ops->prepare_write(NULL, page, from, to);
  304. if (err == 0) {
  305. de->inode = inode->i_ino;
  306. err = dir_commit_chunk(page, from, to);
  307. }
  308. UnlockPage(page);
  309. dir_put_page(page);
  310. dir->i_mtime = dir->i_ctime = CURRENT_TIME;
  311. mark_inode_dirty(dir);
  312. }
  313. struct minix_dir_entry * minix_dotdot (struct inode *dir, struct page **p)
  314. {
  315. struct page *page = dir_get_page(dir, 0);
  316. struct minix_sb_info *sbi = &dir->i_sb->u.minix_sb;
  317. struct minix_dir_entry *de = NULL;
  318. if (!IS_ERR(page)) {
  319. de = minix_next_entry(page_address(page), sbi);
  320. *p = page;
  321. }
  322. return de;
  323. }
  324. ino_t minix_inode_by_name(struct dentry *dentry)
  325. {
  326. struct page *page;
  327. struct minix_dir_entry *de = minix_find_entry(dentry, &page);
  328. ino_t res = 0;
  329. if (de) {
  330. res = de->inode;
  331. dir_put_page(page);
  332. }
  333. return res;
  334. }