dir-ecos.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. /*
  2. * JFFS2 -- Journalling Flash File System, Version 2.
  3. *
  4. * Copyright (C) 2001-2003 Free Software Foundation, Inc.
  5. *
  6. * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
  7. *
  8. * For licensing information, see the file 'LICENCE' in this directory.
  9. *
  10. * $Id: dir-ecos.c,v 1.11 2005/02/08 19:36:27 lunn Exp $
  11. *
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/crc32.h>
  15. #include "nodelist.h"
  16. /***********************************************************************/
  17. /* Takes length argument because it can be either NUL-terminated or '/'-terminated */
  18. struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, int namelen)
  19. {
  20. struct jffs2_inode_info *dir_f;
  21. struct jffs2_full_dirent *fd = NULL, *fd_list;
  22. uint32_t ino = 0;
  23. uint32_t hash = full_name_hash(d_name, namelen);
  24. struct _inode *inode = NULL;
  25. D1(printk("jffs2_lookup()\n"));
  26. dir_f = JFFS2_INODE_INFO(dir_i);
  27. down(&dir_f->sem);
  28. /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
  29. for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= hash; fd_list = fd_list->next) {
  30. if (fd_list->nhash == hash &&
  31. (!fd || fd_list->version > fd->version) &&
  32. strlen((char *)fd_list->name) == namelen &&
  33. !strncmp((char *)fd_list->name, (char *)d_name, namelen)) {
  34. fd = fd_list;
  35. }
  36. }
  37. if (fd)
  38. ino = fd->ino;
  39. up(&dir_f->sem);
  40. if (ino) {
  41. inode = jffs2_iget(dir_i->i_sb, ino);
  42. if (IS_ERR(inode)) {
  43. printk("jffs2_iget() failed for ino #%u\n", ino);
  44. return inode;
  45. }
  46. }
  47. return inode;
  48. }
  49. /***********************************************************************/
  50. int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
  51. struct _inode **new_i)
  52. {
  53. struct jffs2_raw_inode *ri;
  54. struct jffs2_inode_info *f, *dir_f;
  55. struct jffs2_sb_info *c;
  56. struct _inode *inode;
  57. int ret;
  58. ri = jffs2_alloc_raw_inode();
  59. if (!ri)
  60. return -ENOMEM;
  61. c = JFFS2_SB_INFO(dir_i->i_sb);
  62. D1(printk(KERN_DEBUG "jffs2_create()\n"));
  63. inode = jffs2_new_inode(dir_i, mode, ri);
  64. if (IS_ERR(inode)) {
  65. D1(printk(KERN_DEBUG "jffs2_new_inode() failed\n"));
  66. jffs2_free_raw_inode(ri);
  67. return PTR_ERR(inode);
  68. }
  69. f = JFFS2_INODE_INFO(inode);
  70. dir_f = JFFS2_INODE_INFO(dir_i);
  71. ret = jffs2_do_create(c, dir_f, f, ri,
  72. (const char *)d_name,
  73. strlen((char *)d_name));
  74. if (ret) {
  75. inode->i_nlink = 0;
  76. jffs2_iput(inode);
  77. jffs2_free_raw_inode(ri);
  78. return ret;
  79. }
  80. jffs2_free_raw_inode(ri);
  81. D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
  82. inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink));
  83. *new_i = inode;
  84. return 0;
  85. }
  86. /***********************************************************************/
  87. int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
  88. {
  89. struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
  90. struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
  91. struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode);
  92. int ret;
  93. ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
  94. strlen((char *)d_name), dead_f);
  95. if (dead_f->inocache)
  96. d_inode->i_nlink = dead_f->inocache->nlink;
  97. return ret;
  98. }
  99. /***********************************************************************/
  100. int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name)
  101. {
  102. struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
  103. struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode);
  104. struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
  105. int ret;
  106. /* XXX: This is ugly */
  107. uint8_t type = (old_d_inode->i_mode & S_IFMT) >> 12;
  108. if (!type) type = DT_REG;
  109. ret = jffs2_do_link(c, dir_f, f->inocache->ino, type,
  110. (const char * )d_name,
  111. strlen((char *)d_name));
  112. if (!ret) {
  113. down(&f->sem);
  114. old_d_inode->i_nlink = ++f->inocache->nlink;
  115. up(&f->sem);
  116. }
  117. return ret;
  118. }
  119. int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
  120. {
  121. struct jffs2_inode_info *f, *dir_f;
  122. struct jffs2_sb_info *c;
  123. struct _inode *inode;
  124. struct jffs2_raw_inode *ri;
  125. struct jffs2_raw_dirent *rd;
  126. struct jffs2_full_dnode *fn;
  127. struct jffs2_full_dirent *fd;
  128. int namelen;
  129. uint32_t alloclen, phys_ofs;
  130. int ret;
  131. mode |= S_IFDIR;
  132. ri = jffs2_alloc_raw_inode();
  133. if (!ri)
  134. return -ENOMEM;
  135. c = JFFS2_SB_INFO(dir_i->i_sb);
  136. /* Try to reserve enough space for both node and dirent.
  137. * Just the node will do for now, though
  138. */
  139. namelen = strlen((char *)d_name);
  140. ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
  141. if (ret) {
  142. jffs2_free_raw_inode(ri);
  143. return ret;
  144. }
  145. inode = jffs2_new_inode(dir_i, mode, ri);
  146. if (IS_ERR(inode)) {
  147. jffs2_free_raw_inode(ri);
  148. jffs2_complete_reservation(c);
  149. return PTR_ERR(inode);
  150. }
  151. f = JFFS2_INODE_INFO(inode);
  152. ri->data_crc = cpu_to_je32(0);
  153. ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
  154. fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
  155. jffs2_free_raw_inode(ri);
  156. if (IS_ERR(fn)) {
  157. /* Eeek. Wave bye bye */
  158. up(&f->sem);
  159. jffs2_complete_reservation(c);
  160. inode->i_nlink = 0;
  161. jffs2_iput(inode);
  162. return PTR_ERR(fn);
  163. }
  164. /* No data here. Only a metadata node, which will be
  165. obsoleted by the first data write
  166. */
  167. f->metadata = fn;
  168. up(&f->sem);
  169. jffs2_complete_reservation(c);
  170. ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
  171. if (ret) {
  172. /* Eep. */
  173. inode->i_nlink = 0;
  174. jffs2_iput(inode);
  175. return ret;
  176. }
  177. rd = jffs2_alloc_raw_dirent();
  178. if (!rd) {
  179. /* Argh. Now we treat it like a normal delete */
  180. jffs2_complete_reservation(c);
  181. inode->i_nlink = 0;
  182. jffs2_iput(inode);
  183. return -ENOMEM;
  184. }
  185. dir_f = JFFS2_INODE_INFO(dir_i);
  186. down(&dir_f->sem);
  187. rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
  188. rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
  189. rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
  190. rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
  191. rd->pino = cpu_to_je32(dir_i->i_ino);
  192. rd->version = cpu_to_je32(++dir_f->highest_version);
  193. rd->ino = cpu_to_je32(inode->i_ino);
  194. rd->mctime = cpu_to_je32(jffs2_get_timestamp());
  195. rd->nsize = namelen;
  196. rd->type = DT_DIR;
  197. rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
  198. rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen));
  199. fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL);
  200. jffs2_complete_reservation(c);
  201. jffs2_free_raw_dirent(rd);
  202. if (IS_ERR(fd)) {
  203. /* dirent failed to write. Delete the inode normally
  204. as if it were the final unlink() */
  205. up(&dir_f->sem);
  206. inode->i_nlink = 0;
  207. jffs2_iput(inode);
  208. return PTR_ERR(fd);
  209. }
  210. /* Link the fd into the inode's list, obsoleting an old
  211. one if necessary. */
  212. jffs2_add_fd_to_list(c, fd, &dir_f->dents);
  213. up(&dir_f->sem);
  214. jffs2_iput(inode);
  215. return 0;
  216. }
  217. int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
  218. {
  219. struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
  220. struct jffs2_full_dirent *fd;
  221. for (fd = f->dents ; fd; fd = fd->next) {
  222. if (fd->ino)
  223. return EPERM; //-ENOTEMPTY;
  224. }
  225. return jffs2_unlink(dir_i, d_inode, d_name);
  226. }
  227. int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
  228. struct _inode *new_dir_i, const unsigned char *new_d_name)
  229. {
  230. int ret;
  231. struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
  232. struct jffs2_inode_info *victim_f = NULL;
  233. uint8_t type;
  234. #if 0 /* FIXME -- this really doesn't belong in individual file systems.
  235. The fileio code ought to do this for us, or at least part of it */
  236. if (new_dentry->d_inode) {
  237. if (S_ISDIR(d_inode->i_mode) &&
  238. !S_ISDIR(new_dentry->d_inode->i_mode)) {
  239. /* Cannot rename directory over non-directory */
  240. return -EINVAL;
  241. }
  242. victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
  243. if (S_ISDIR(new_dentry->d_inode->i_mode)) {
  244. struct jffs2_full_dirent *fd;
  245. if (!S_ISDIR(d_inode->i_mode)) {
  246. /* Cannot rename non-directory over directory */
  247. return -EINVAL;
  248. }
  249. down(&victim_f->sem);
  250. for (fd = victim_f->dents; fd; fd = fd->next) {
  251. if (fd->ino) {
  252. up(&victim_f->sem);
  253. return -ENOTEMPTY;
  254. }
  255. }
  256. up(&victim_f->sem);
  257. }
  258. }
  259. #endif
  260. /* XXX: We probably ought to alloc enough space for
  261. both nodes at the same time. Writing the new link,
  262. then getting -ENOSPC, is quite bad :)
  263. */
  264. /* Make a hard link */
  265. /* XXX: This is ugly */
  266. type = (d_inode->i_mode & S_IFMT) >> 12;
  267. if (!type) type = DT_REG;
  268. ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
  269. d_inode->i_ino, type,
  270. (const char *)new_d_name,
  271. strlen((char *)new_d_name));
  272. if (ret)
  273. return ret;
  274. if (victim_f) {
  275. /* There was a victim. Kill it off nicely */
  276. /* Don't oops if the victim was a dirent pointing to an
  277. inode which didn't exist. */
  278. if (victim_f->inocache) {
  279. down(&victim_f->sem);
  280. victim_f->inocache->nlink--;
  281. up(&victim_f->sem);
  282. }
  283. }
  284. /* Unlink the original */
  285. ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
  286. (const char *)old_d_name,
  287. strlen((char *)old_d_name), NULL);
  288. if (ret) {
  289. /* Oh shit. We really ought to make a single node which can do both atomically */
  290. struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
  291. down(&f->sem);
  292. if (f->inocache)
  293. d_inode->i_nlink = f->inocache->nlink++;
  294. up(&f->sem);
  295. printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
  296. }
  297. return ret;
  298. }