namei.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:7k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * linux/fs/ufs/namei.c
  3.  *
  4.  * Copyright (C) 1998
  5.  * Daniel Pirkl <daniel.pirkl@email.cz>
  6.  * Charles University, Faculty of Mathematics and Physics
  7.  *
  8.  *  from
  9.  *
  10.  *  linux/fs/ext2/namei.c
  11.  *
  12.  * Copyright (C) 1992, 1993, 1994, 1995
  13.  * Remy Card (card@masi.ibp.fr)
  14.  * Laboratoire MASI - Institut Blaise Pascal
  15.  * Universite Pierre et Marie Curie (Paris VI)
  16.  *
  17.  *  from
  18.  *
  19.  *  linux/fs/minix/namei.c
  20.  *
  21.  *  Copyright (C) 1991, 1992  Linus Torvalds
  22.  *
  23.  *  Big-endian to little-endian byte-swapping/bitmaps by
  24.  *        David S. Miller (davem@caip.rutgers.edu), 1995
  25.  */
  26. #include <linux/sched.h>
  27. #include <linux/fs.h>
  28. #include <linux/ufs_fs.h>
  29. #undef UFS_NAMEI_DEBUG
  30. #ifdef UFS_NAMEI_DEBUG
  31. #define UFSD(x) printk("(%s, %d), %s: ", __FILE__, __LINE__, __FUNCTION__); printk x;
  32. #else
  33. #define UFSD(x)
  34. #endif
  35. static inline void ufs_inc_count(struct inode *inode)
  36. {
  37. inode->i_nlink++;
  38. mark_inode_dirty(inode);
  39. }
  40. static inline void ufs_dec_count(struct inode *inode)
  41. {
  42. inode->i_nlink--;
  43. mark_inode_dirty(inode);
  44. }
  45. static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
  46. {
  47. int err = ufs_add_link(dentry, inode);
  48. if (!err) {
  49. d_instantiate(dentry, inode);
  50. return 0;
  51. }
  52. ufs_dec_count(inode);
  53. iput(inode);
  54. return err;
  55. }
  56. static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry)
  57. {
  58. struct inode * inode = NULL;
  59. ino_t ino;
  60. if (dentry->d_name.len > UFS_MAXNAMLEN)
  61. return ERR_PTR(-ENAMETOOLONG);
  62. ino = ufs_inode_by_name(dir, dentry);
  63. if (ino) {
  64. inode = iget(dir->i_sb, ino);
  65. if (!inode) 
  66. return ERR_PTR(-EACCES);
  67. }
  68. d_add(dentry, inode);
  69. return NULL;
  70. }
  71. /*
  72.  * By the time this is called, we already have created
  73.  * the directory cache entry for the new file, but it
  74.  * is so far negative - it has no inode.
  75.  *
  76.  * If the create succeeds, we fill in the inode information
  77.  * with d_instantiate(). 
  78.  */
  79. static int ufs_create (struct inode * dir, struct dentry * dentry, int mode)
  80. {
  81. struct inode * inode = ufs_new_inode(dir, mode);
  82. int err = PTR_ERR(inode);
  83. if (!IS_ERR(inode)) {
  84. inode->i_op = &ufs_file_inode_operations;
  85. inode->i_fop = &ufs_file_operations;
  86. inode->i_mapping->a_ops = &ufs_aops;
  87. mark_inode_dirty(inode);
  88. err = ufs_add_nondir(dentry, inode);
  89. }
  90. return err;
  91. }
  92. static int ufs_mknod (struct inode * dir, struct dentry *dentry, int mode, int rdev)
  93. {
  94. struct inode * inode = ufs_new_inode(dir, mode);
  95. int err = PTR_ERR(inode);
  96. if (!IS_ERR(inode)) {
  97. init_special_inode(inode, mode, rdev);
  98. mark_inode_dirty(inode);
  99. err = ufs_add_nondir(dentry, inode);
  100. }
  101. return err;
  102. }
  103. static int ufs_symlink (struct inode * dir, struct dentry * dentry,
  104. const char * symname)
  105. {
  106. struct super_block * sb = dir->i_sb;
  107. int err = -ENAMETOOLONG;
  108. unsigned l = strlen(symname)+1;
  109. struct inode * inode;
  110. if (l > sb->s_blocksize)
  111. goto out;
  112. inode = ufs_new_inode(dir, S_IFLNK | S_IRWXUGO);
  113. err = PTR_ERR(inode);
  114. if (IS_ERR(inode))
  115. goto out;
  116. if (l > sb->u.ufs_sb.s_uspi->s_maxsymlinklen) {
  117. /* slow symlink */
  118. inode->i_op = &page_symlink_inode_operations;
  119. inode->i_mapping->a_ops = &ufs_aops;
  120. err = block_symlink(inode, symname, l);
  121. if (err)
  122. goto out_fail;
  123. } else {
  124. /* fast symlink */
  125. inode->i_op = &ufs_fast_symlink_inode_operations;
  126. memcpy((char*)&inode->u.ufs_i.i_u1.i_data,symname,l);
  127. inode->i_size = l-1;
  128. }
  129. mark_inode_dirty(inode);
  130. err = ufs_add_nondir(dentry, inode);
  131. out:
  132. return err;
  133. out_fail:
  134. ufs_dec_count(inode);
  135. iput(inode);
  136. goto out;
  137. }
  138. static int ufs_link (struct dentry * old_dentry, struct inode * dir,
  139. struct dentry *dentry)
  140. {
  141. struct inode *inode = old_dentry->d_inode;
  142. if (S_ISDIR(inode->i_mode))
  143. return -EPERM;
  144. if (inode->i_nlink >= UFS_LINK_MAX)
  145. return -EMLINK;
  146. inode->i_ctime = CURRENT_TIME;
  147. ufs_inc_count(inode);
  148. atomic_inc(&inode->i_count);
  149. return ufs_add_nondir(dentry, inode);
  150. }
  151. static int ufs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
  152. {
  153. struct inode * inode;
  154. int err = -EMLINK;
  155. if (dir->i_nlink >= UFS_LINK_MAX)
  156. goto out;
  157. ufs_inc_count(dir);
  158. inode = ufs_new_inode(dir, S_IFDIR|mode);
  159. err = PTR_ERR(inode);
  160. if (IS_ERR(inode))
  161. goto out_dir;
  162. inode->i_op = &ufs_dir_inode_operations;
  163. inode->i_fop = &ufs_dir_operations;
  164. ufs_inc_count(inode);
  165. err = ufs_make_empty(inode, dir);
  166. if (err)
  167. goto out_fail;
  168. err = ufs_add_link(dentry, inode);
  169. if (err)
  170. goto out_fail;
  171. d_instantiate(dentry, inode);
  172. out:
  173. return err;
  174. out_fail:
  175. ufs_dec_count(inode);
  176. ufs_dec_count(inode);
  177. iput (inode);
  178. out_dir:
  179. ufs_dec_count(dir);
  180. goto out;
  181. }
  182. static int ufs_unlink(struct inode * dir, struct dentry *dentry)
  183. {
  184. struct inode * inode = dentry->d_inode;
  185. struct buffer_head * bh;
  186. struct ufs_dir_entry * de;
  187. int err = -ENOENT;
  188. de = ufs_find_entry (dentry, &bh);
  189. if (!de)
  190. goto out;
  191. err = ufs_delete_entry (dir, de, bh);
  192. if (err)
  193. goto out;
  194. inode->i_ctime = dir->i_ctime;
  195. ufs_dec_count(inode);
  196. err = 0;
  197. out:
  198. return err;
  199. }
  200. static int ufs_rmdir (struct inode * dir, struct dentry *dentry)
  201. {
  202. struct inode * inode = dentry->d_inode;
  203. int err= -ENOTEMPTY;
  204. if (ufs_empty_dir (inode)) {
  205. err = ufs_unlink(dir, dentry);
  206. if (!err) {
  207. inode->i_size = 0;
  208. ufs_dec_count(inode);
  209. ufs_dec_count(dir);
  210. }
  211. }
  212. return err;
  213. }
  214. static int ufs_rename (struct inode * old_dir, struct dentry * old_dentry,
  215. struct inode * new_dir, struct dentry * new_dentry )
  216. {
  217. struct inode *old_inode = old_dentry->d_inode;
  218. struct inode *new_inode = new_dentry->d_inode;
  219. struct buffer_head *dir_bh = NULL;
  220. struct ufs_dir_entry *dir_de = NULL;
  221. struct buffer_head *old_bh;
  222. struct ufs_dir_entry *old_de;
  223. int err = -ENOENT;
  224. old_de = ufs_find_entry (old_dentry, &old_bh);
  225. if (!old_de)
  226. goto out;
  227. if (S_ISDIR(old_inode->i_mode)) {
  228. err = -EIO;
  229. dir_de = ufs_dotdot(old_inode, &dir_bh);
  230. if (!dir_de)
  231. goto out_old;
  232. }
  233. if (new_inode) {
  234. struct buffer_head *new_bh;
  235. struct ufs_dir_entry *new_de;
  236. err = -ENOTEMPTY;
  237. if (dir_de && !ufs_empty_dir (new_inode))
  238. goto out_dir;
  239. err = -ENOENT;
  240. new_de = ufs_find_entry (new_dentry, &new_bh);
  241. if (!new_de)
  242. goto out_dir;
  243. ufs_inc_count(old_inode);
  244. ufs_set_link(new_dir, new_de, new_bh, old_inode);
  245. new_inode->i_ctime = CURRENT_TIME;
  246. if (dir_de)
  247. new_inode->i_nlink--;
  248. ufs_dec_count(new_inode);
  249. } else {
  250. if (dir_de) {
  251. err = -EMLINK;
  252. if (new_dir->i_nlink >= UFS_LINK_MAX)
  253. goto out_dir;
  254. }
  255. ufs_inc_count(old_inode);
  256. err = ufs_add_link(new_dentry, old_inode);
  257. if (err) {
  258. ufs_dec_count(old_inode);
  259. goto out_dir;
  260. }
  261. if (dir_de)
  262. ufs_inc_count(new_dir);
  263. }
  264. ufs_delete_entry (old_dir, old_de, old_bh);
  265. ufs_dec_count(old_inode);
  266. if (dir_de) {
  267. ufs_set_link(old_inode, dir_de, dir_bh, new_dir);
  268. ufs_dec_count(old_dir);
  269. }
  270. return 0;
  271. out_dir:
  272. if (dir_de)
  273. brelse(dir_bh);
  274. out_old:
  275. brelse (old_bh);
  276. out:
  277. return err;
  278. }
  279. struct inode_operations ufs_dir_inode_operations = {
  280. create: ufs_create,
  281. lookup: ufs_lookup,
  282. link: ufs_link,
  283. unlink: ufs_unlink,
  284. symlink: ufs_symlink,
  285. mkdir: ufs_mkdir,
  286. rmdir: ufs_rmdir,
  287. mknod: ufs_mknod,
  288. rename: ufs_rename,
  289. };