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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/fs/open.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6. #include <linux/string.h>
  7. #include <linux/mm.h>
  8. #include <linux/utime.h>
  9. #include <linux/file.h>
  10. #include <linux/smp_lock.h>
  11. #include <linux/quotaops.h>
  12. #include <linux/dnotify.h>
  13. #include <linux/module.h>
  14. #include <linux/slab.h>
  15. #include <linux/tty.h>
  16. #include <linux/iobuf.h>
  17. #include <asm/uaccess.h>
  18. #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
  19. int vfs_statfs(struct super_block *sb, struct statfs *buf)
  20. {
  21. int retval = -ENODEV;
  22. if (sb) {
  23. retval = -ENOSYS;
  24. if (sb->s_op && sb->s_op->statfs) {
  25. memset(buf, 0, sizeof(struct statfs));
  26. lock_kernel();
  27. retval = sb->s_op->statfs(sb, buf);
  28. unlock_kernel();
  29. }
  30. }
  31. return retval;
  32. }
  33. asmlinkage long sys_statfs(const char * path, struct statfs * buf)
  34. {
  35. struct nameidata nd;
  36. int error;
  37. error = user_path_walk(path, &nd);
  38. if (!error) {
  39. struct statfs tmp;
  40. error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
  41. if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
  42. error = -EFAULT;
  43. path_release(&nd);
  44. }
  45. return error;
  46. }
  47. asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf)
  48. {
  49. struct file * file;
  50. struct statfs tmp;
  51. int error;
  52. error = -EBADF;
  53. file = fget(fd);
  54. if (!file)
  55. goto out;
  56. error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
  57. if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
  58. error = -EFAULT;
  59. fput(file);
  60. out:
  61. return error;
  62. }
  63. /*
  64.  * Install a file pointer in the fd array.  
  65.  *
  66.  * The VFS is full of places where we drop the files lock between
  67.  * setting the open_fds bitmap and installing the file in the file
  68.  * array.  At any such point, we are vulnerable to a dup2() race
  69.  * installing a file in the array before us.  We need to detect this and
  70.  * fput() the struct file we are about to overwrite in this case.
  71.  *
  72.  * It should never happen - if we allow dup2() do it, _really_ bad things
  73.  * will follow.
  74.  */
  75. void fd_install(unsigned int fd, struct file * file)
  76. {
  77. struct files_struct *files = current->files;
  78. write_lock(&files->file_lock);
  79. if (files->fd[fd])
  80. BUG();
  81. files->fd[fd] = file;
  82. write_unlock(&files->file_lock);
  83. }
  84. int do_truncate(struct dentry *dentry, loff_t length)
  85. {
  86. struct inode *inode = dentry->d_inode;
  87. int error;
  88. struct iattr newattrs;
  89. /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
  90. if (length < 0)
  91. return -EINVAL;
  92. down(&inode->i_sem);
  93. newattrs.ia_size = length;
  94. newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
  95. error = notify_change(dentry, &newattrs);
  96. up(&inode->i_sem);
  97. return error;
  98. }
  99. static inline long do_sys_truncate(const char * path, loff_t length)
  100. {
  101. struct nameidata nd;
  102. struct inode * inode;
  103. int error;
  104. error = -EINVAL;
  105. if (length < 0) /* sorry, but loff_t says... */
  106. goto out;
  107. error = user_path_walk(path, &nd);
  108. if (error)
  109. goto out;
  110. inode = nd.dentry->d_inode;
  111. /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
  112. error = -EISDIR;
  113. if (S_ISDIR(inode->i_mode))
  114. goto dput_and_out;
  115. error = -EINVAL;
  116. if (!S_ISREG(inode->i_mode))
  117. goto dput_and_out;
  118. error = permission(inode,MAY_WRITE);
  119. if (error)
  120. goto dput_and_out;
  121. error = -EROFS;
  122. if (IS_RDONLY(inode))
  123. goto dput_and_out;
  124. error = -EPERM;
  125. if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  126. goto dput_and_out;
  127. /*
  128.  * Make sure that there are no leases.
  129.  */
  130. error = get_lease(inode, FMODE_WRITE);
  131. if (error)
  132. goto dput_and_out;
  133. error = get_write_access(inode);
  134. if (error)
  135. goto dput_and_out;
  136. error = locks_verify_truncate(inode, NULL, length);
  137. if (!error) {
  138. DQUOT_INIT(inode);
  139. error = do_truncate(nd.dentry, length);
  140. }
  141. put_write_access(inode);
  142. dput_and_out:
  143. path_release(&nd);
  144. out:
  145. return error;
  146. }
  147. asmlinkage long sys_truncate(const char * path, unsigned long length)
  148. {
  149. /* on 32-bit boxen it will cut the range 2^31--2^32-1 off */
  150. return do_sys_truncate(path, (long)length);
  151. }
  152. static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
  153. {
  154. struct inode * inode;
  155. struct dentry *dentry;
  156. struct file * file;
  157. int error;
  158. error = -EINVAL;
  159. if (length < 0)
  160. goto out;
  161. error = -EBADF;
  162. file = fget(fd);
  163. if (!file)
  164. goto out;
  165. /* explicitly opened as large or we are on 64-bit box */
  166. if (file->f_flags & O_LARGEFILE)
  167. small = 0;
  168. dentry = file->f_dentry;
  169. inode = dentry->d_inode;
  170. error = -EINVAL;
  171. if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
  172. goto out_putf;
  173. error = -EINVAL;
  174. /* Cannot ftruncate over 2^31 bytes without large file support */
  175. if (small && length > MAX_NON_LFS)
  176. goto out_putf;
  177. error = -EPERM;
  178. if (IS_APPEND(inode))
  179. goto out_putf;
  180. error = locks_verify_truncate(inode, file, length);
  181. if (!error)
  182. error = do_truncate(dentry, length);
  183. out_putf:
  184. fput(file);
  185. out:
  186. return error;
  187. }
  188. asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
  189. {
  190. return do_sys_ftruncate(fd, length, 1);
  191. }
  192. /* LFS versions of truncate are only needed on 32 bit machines */
  193. #if BITS_PER_LONG == 32
  194. asmlinkage long sys_truncate64(const char * path, loff_t length)
  195. {
  196. return do_sys_truncate(path, length);
  197. }
  198. asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
  199. {
  200. return do_sys_ftruncate(fd, length, 0);
  201. }
  202. #endif
  203. #if !(defined(__alpha__) || defined(__ia64__))
  204. /*
  205.  * sys_utime() can be implemented in user-level using sys_utimes().
  206.  * Is this for backwards compatibility?  If so, why not move it
  207.  * into the appropriate arch directory (for those architectures that
  208.  * need it).
  209.  */
  210. /* If times==NULL, set access and modification to current time,
  211.  * must be owner or have write permission.
  212.  * Else, update from *times, must be owner or super user.
  213.  */
  214. asmlinkage long sys_utime(char * filename, struct utimbuf * times)
  215. {
  216. int error;
  217. struct nameidata nd;
  218. struct inode * inode;
  219. struct iattr newattrs;
  220. error = user_path_walk(filename, &nd);
  221. if (error)
  222. goto out;
  223. inode = nd.dentry->d_inode;
  224. error = -EROFS;
  225. if (IS_RDONLY(inode))
  226. goto dput_and_out;
  227. /* Don't worry, the checks are done in inode_change_ok() */
  228. newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
  229. if (times) {
  230. error = get_user(newattrs.ia_atime, &times->actime);
  231. if (!error) 
  232. error = get_user(newattrs.ia_mtime, &times->modtime);
  233. if (error)
  234. goto dput_and_out;
  235. newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
  236. } else {
  237. if (current->fsuid != inode->i_uid &&
  238.     (error = permission(inode,MAY_WRITE)) != 0)
  239. goto dput_and_out;
  240. }
  241. error = notify_change(nd.dentry, &newattrs);
  242. dput_and_out:
  243. path_release(&nd);
  244. out:
  245. return error;
  246. }
  247. #endif
  248. /* If times==NULL, set access and modification to current time,
  249.  * must be owner or have write permission.
  250.  * Else, update from *times, must be owner or super user.
  251.  */
  252. asmlinkage long sys_utimes(char * filename, struct timeval * utimes)
  253. {
  254. int error;
  255. struct nameidata nd;
  256. struct inode * inode;
  257. struct iattr newattrs;
  258. error = user_path_walk(filename, &nd);
  259. if (error)
  260. goto out;
  261. inode = nd.dentry->d_inode;
  262. error = -EROFS;
  263. if (IS_RDONLY(inode))
  264. goto dput_and_out;
  265. /* Don't worry, the checks are done in inode_change_ok() */
  266. newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
  267. if (utimes) {
  268. struct timeval times[2];
  269. error = -EFAULT;
  270. if (copy_from_user(&times, utimes, sizeof(times)))
  271. goto dput_and_out;
  272. newattrs.ia_atime = times[0].tv_sec;
  273. newattrs.ia_mtime = times[1].tv_sec;
  274. newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
  275. } else {
  276. if (current->fsuid != inode->i_uid &&
  277.     (error = permission(inode,MAY_WRITE)) != 0)
  278. goto dput_and_out;
  279. }
  280. error = notify_change(nd.dentry, &newattrs);
  281. dput_and_out:
  282. path_release(&nd);
  283. out:
  284. return error;
  285. }
  286. /*
  287.  * access() needs to use the real uid/gid, not the effective uid/gid.
  288.  * We do this by temporarily clearing all FS-related capabilities and
  289.  * switching the fsuid/fsgid around to the real ones.
  290.  */
  291. asmlinkage long sys_access(const char * filename, int mode)
  292. {
  293. struct nameidata nd;
  294. int old_fsuid, old_fsgid;
  295. kernel_cap_t old_cap;
  296. int res;
  297. if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
  298. return -EINVAL;
  299. old_fsuid = current->fsuid;
  300. old_fsgid = current->fsgid;
  301. old_cap = current->cap_effective;
  302. current->fsuid = current->uid;
  303. current->fsgid = current->gid;
  304. /* Clear the capabilities if we switch to a non-root user */
  305. if (current->uid)
  306. cap_clear(current->cap_effective);
  307. else
  308. current->cap_effective = current->cap_permitted;
  309. res = user_path_walk(filename, &nd);
  310. if (!res) {
  311. res = permission(nd.dentry->d_inode, mode);
  312. /* SuS v2 requires we report a read only fs too */
  313. if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
  314.    && !special_file(nd.dentry->d_inode->i_mode))
  315. res = -EROFS;
  316. path_release(&nd);
  317. }
  318. current->fsuid = old_fsuid;
  319. current->fsgid = old_fsgid;
  320. current->cap_effective = old_cap;
  321. return res;
  322. }
  323. asmlinkage long sys_chdir(const char * filename)
  324. {
  325. int error;
  326. struct nameidata nd;
  327. error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
  328. if (error)
  329. goto out;
  330. error = permission(nd.dentry->d_inode,MAY_EXEC);
  331. if (error)
  332. goto dput_and_out;
  333. set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  334. dput_and_out:
  335. path_release(&nd);
  336. out:
  337. return error;
  338. }
  339. asmlinkage long sys_fchdir(unsigned int fd)
  340. {
  341. struct file *file;
  342. struct dentry *dentry;
  343. struct inode *inode;
  344. struct vfsmount *mnt;
  345. int error;
  346. error = -EBADF;
  347. file = fget(fd);
  348. if (!file)
  349. goto out;
  350. dentry = file->f_dentry;
  351. mnt = file->f_vfsmnt;
  352. inode = dentry->d_inode;
  353. error = -ENOTDIR;
  354. if (!S_ISDIR(inode->i_mode))
  355. goto out_putf;
  356. error = permission(inode, MAY_EXEC);
  357. if (!error)
  358. set_fs_pwd(current->fs, mnt, dentry);
  359. out_putf:
  360. fput(file);
  361. out:
  362. return error;
  363. }
  364. asmlinkage long sys_chroot(const char * filename)
  365. {
  366. int error;
  367. struct nameidata nd;
  368. error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
  369.       LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
  370. if (error)
  371. goto out;
  372. error = permission(nd.dentry->d_inode,MAY_EXEC);
  373. if (error)
  374. goto dput_and_out;
  375. error = -EPERM;
  376. if (!capable(CAP_SYS_CHROOT))
  377. goto dput_and_out;
  378. set_fs_root(current->fs, nd.mnt, nd.dentry);
  379. set_fs_altroot();
  380. error = 0;
  381. dput_and_out:
  382. path_release(&nd);
  383. out:
  384. return error;
  385. }
  386. asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
  387. {
  388. struct inode * inode;
  389. struct dentry * dentry;
  390. struct file * file;
  391. int err = -EBADF;
  392. struct iattr newattrs;
  393. file = fget(fd);
  394. if (!file)
  395. goto out;
  396. dentry = file->f_dentry;
  397. inode = dentry->d_inode;
  398. err = -EROFS;
  399. if (IS_RDONLY(inode))
  400. goto out_putf;
  401. err = -EPERM;
  402. if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  403. goto out_putf;
  404. if (mode == (mode_t) -1)
  405. mode = inode->i_mode;
  406. newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  407. newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
  408. err = notify_change(dentry, &newattrs);
  409. out_putf:
  410. fput(file);
  411. out:
  412. return err;
  413. }
  414. asmlinkage long sys_chmod(const char * filename, mode_t mode)
  415. {
  416. struct nameidata nd;
  417. struct inode * inode;
  418. int error;
  419. struct iattr newattrs;
  420. error = user_path_walk(filename, &nd);
  421. if (error)
  422. goto out;
  423. inode = nd.dentry->d_inode;
  424. error = -EROFS;
  425. if (IS_RDONLY(inode))
  426. goto dput_and_out;
  427. error = -EPERM;
  428. if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  429. goto dput_and_out;
  430. if (mode == (mode_t) -1)
  431. mode = inode->i_mode;
  432. newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  433. newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
  434. error = notify_change(nd.dentry, &newattrs);
  435. dput_and_out:
  436. path_release(&nd);
  437. out:
  438. return error;
  439. }
  440. static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
  441. {
  442. struct inode * inode;
  443. int error;
  444. struct iattr newattrs;
  445. error = -ENOENT;
  446. if (!(inode = dentry->d_inode)) {
  447. printk(KERN_ERR "chown_common: NULL inoden");
  448. goto out;
  449. }
  450. error = -EROFS;
  451. if (IS_RDONLY(inode))
  452. goto out;
  453. error = -EPERM;
  454. if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  455. goto out;
  456. if (user == (uid_t) -1)
  457. user = inode->i_uid;
  458. if (group == (gid_t) -1)
  459. group = inode->i_gid;
  460. newattrs.ia_mode = inode->i_mode;
  461. newattrs.ia_uid = user;
  462. newattrs.ia_gid = group;
  463. newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
  464. /*
  465.  * If the user or group of a non-directory has been changed by a
  466.  * non-root user, remove the setuid bit.
  467.  * 19981026 David C Niemi <niemi@tux.org>
  468.  *
  469.  * Changed this to apply to all users, including root, to avoid
  470.  * some races. This is the behavior we had in 2.0. The check for
  471.  * non-root was definitely wrong for 2.2 anyway, as it should
  472.  * have been using CAP_FSETID rather than fsuid -- 19990830 SD.
  473.  */
  474. if ((inode->i_mode & S_ISUID) == S_ISUID &&
  475. !S_ISDIR(inode->i_mode))
  476. {
  477. newattrs.ia_mode &= ~S_ISUID;
  478. newattrs.ia_valid |= ATTR_MODE;
  479. }
  480. /*
  481.  * Likewise, if the user or group of a non-directory has been changed
  482.  * by a non-root user, remove the setgid bit UNLESS there is no group
  483.  * execute bit (this would be a file marked for mandatory locking).
  484.  * 19981026 David C Niemi <niemi@tux.org>
  485.  *
  486.  * Removed the fsuid check (see the comment above) -- 19990830 SD.
  487.  */
  488. if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) 
  489. && !S_ISDIR(inode->i_mode))
  490. {
  491. newattrs.ia_mode &= ~S_ISGID;
  492. newattrs.ia_valid |= ATTR_MODE;
  493. }
  494. error = notify_change(dentry, &newattrs);
  495. out:
  496. return error;
  497. }
  498. asmlinkage long sys_chown(const char * filename, uid_t user, gid_t group)
  499. {
  500. struct nameidata nd;
  501. int error;
  502. error = user_path_walk(filename, &nd);
  503. if (!error) {
  504. error = chown_common(nd.dentry, user, group);
  505. path_release(&nd);
  506. }
  507. return error;
  508. }
  509. asmlinkage long sys_lchown(const char * filename, uid_t user, gid_t group)
  510. {
  511. struct nameidata nd;
  512. int error;
  513. error = user_path_walk_link(filename, &nd);
  514. if (!error) {
  515. error = chown_common(nd.dentry, user, group);
  516. path_release(&nd);
  517. }
  518. return error;
  519. }
  520. asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
  521. {
  522. struct file * file;
  523. int error = -EBADF;
  524. file = fget(fd);
  525. if (file) {
  526. error = chown_common(file->f_dentry, user, group);
  527. fput(file);
  528. }
  529. return error;
  530. }
  531. /*
  532.  * Note that while the flag value (low two bits) for sys_open means:
  533.  * 00 - read-only
  534.  * 01 - write-only
  535.  * 10 - read-write
  536.  * 11 - special
  537.  * it is changed into
  538.  * 00 - no permissions needed
  539.  * 01 - read-permission
  540.  * 10 - write-permission
  541.  * 11 - read-write
  542.  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  543.  * used by symlinks.
  544.  */
  545. struct file *filp_open(const char * filename, int flags, int mode)
  546. {
  547. int namei_flags, error;
  548. struct nameidata nd;
  549. namei_flags = flags;
  550. if ((namei_flags+1) & O_ACCMODE)
  551. namei_flags++;
  552. if (namei_flags & O_TRUNC)
  553. namei_flags |= 2;
  554. error = open_namei(filename, namei_flags, mode, &nd);
  555. if (!error)
  556. return dentry_open(nd.dentry, nd.mnt, flags);
  557. return ERR_PTR(error);
  558. }
  559. struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
  560. {
  561. struct file * f;
  562. struct inode *inode;
  563. static LIST_HEAD(kill_list);
  564. int error;
  565. error = -ENFILE;
  566. f = get_empty_filp();
  567. if (!f)
  568. goto cleanup_dentry;
  569. f->f_flags = flags;
  570. f->f_mode = (flags+1) & O_ACCMODE;
  571. inode = dentry->d_inode;
  572. if (f->f_mode & FMODE_WRITE) {
  573. error = get_write_access(inode);
  574. if (error)
  575. goto cleanup_file;
  576. }
  577. f->f_dentry = dentry;
  578. f->f_vfsmnt = mnt;
  579. f->f_pos = 0;
  580. f->f_reada = 0;
  581. f->f_op = fops_get(inode->i_fop);
  582. file_move(f, &inode->i_sb->s_files);
  583. /* preallocate kiobuf for O_DIRECT */
  584. f->f_iobuf = NULL;
  585. f->f_iobuf_lock = 0;
  586. if (f->f_flags & O_DIRECT) {
  587. error = alloc_kiovec(1, &f->f_iobuf);
  588. if (error)
  589. goto cleanup_all;
  590. }
  591. if (f->f_op && f->f_op->open) {
  592. error = f->f_op->open(inode,f);
  593. if (error)
  594. goto cleanup_all;
  595. }
  596. f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
  597. return f;
  598. cleanup_all:
  599. if (f->f_iobuf)
  600. free_kiovec(1, &f->f_iobuf);
  601. fops_put(f->f_op);
  602. if (f->f_mode & FMODE_WRITE)
  603. put_write_access(inode);
  604. file_move(f, &kill_list); /* out of the way.. */
  605. f->f_dentry = NULL;
  606. f->f_vfsmnt = NULL;
  607. cleanup_file:
  608. put_filp(f);
  609. cleanup_dentry:
  610. dput(dentry);
  611. mntput(mnt);
  612. return ERR_PTR(error);
  613. }
  614. /*
  615.  * Find an empty file descriptor entry, and mark it busy.
  616.  */
  617. int get_unused_fd(void)
  618. {
  619. struct files_struct * files = current->files;
  620. int fd, error;
  621.    error = -EMFILE;
  622. write_lock(&files->file_lock);
  623. repeat:
  624.   fd = find_next_zero_bit(files->open_fds, 
  625. files->max_fdset, 
  626. files->next_fd);
  627. /*
  628.  * N.B. For clone tasks sharing a files structure, this test
  629.  * will limit the total number of files that can be opened.
  630.  */
  631. if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
  632. goto out;
  633. /* Do we need to expand the fdset array? */
  634. if (fd >= files->max_fdset) {
  635. error = expand_fdset(files, fd);
  636. if (!error) {
  637. error = -EMFILE;
  638. goto repeat;
  639. }
  640. goto out;
  641. }
  642. /* 
  643.  * Check whether we need to expand the fd array.
  644.  */
  645. if (fd >= files->max_fds) {
  646. error = expand_fd_array(files, fd);
  647. if (!error) {
  648. error = -EMFILE;
  649. goto repeat;
  650. }
  651. goto out;
  652. }
  653. FD_SET(fd, files->open_fds);
  654. FD_CLR(fd, files->close_on_exec);
  655. files->next_fd = fd + 1;
  656. #if 1
  657. /* Sanity check */
  658. if (files->fd[fd] != NULL) {
  659. printk(KERN_WARNING "get_unused_fd: slot %d not NULL!n", fd);
  660. files->fd[fd] = NULL;
  661. }
  662. #endif
  663. error = fd;
  664. out:
  665. write_unlock(&files->file_lock);
  666. return error;
  667. }
  668. asmlinkage long sys_open(const char * filename, int flags, int mode)
  669. {
  670. char * tmp;
  671. int fd, error;
  672. #if BITS_PER_LONG != 32
  673. flags |= O_LARGEFILE;
  674. #endif
  675. tmp = getname(filename);
  676. fd = PTR_ERR(tmp);
  677. if (!IS_ERR(tmp)) {
  678. fd = get_unused_fd();
  679. if (fd >= 0) {
  680. struct file *f = filp_open(tmp, flags, mode);
  681. error = PTR_ERR(f);
  682. if (IS_ERR(f))
  683. goto out_error;
  684. fd_install(fd, f);
  685. }
  686. out:
  687. putname(tmp);
  688. }
  689. return fd;
  690. out_error:
  691. put_unused_fd(fd);
  692. fd = error;
  693. goto out;
  694. }
  695. #ifndef __alpha__
  696. /*
  697.  * For backward compatibility?  Maybe this should be moved
  698.  * into arch/i386 instead?
  699.  */
  700. asmlinkage long sys_creat(const char * pathname, int mode)
  701. {
  702. return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
  703. }
  704. #endif
  705. /*
  706.  * "id" is the POSIX thread ID. We use the
  707.  * files pointer for this..
  708.  */
  709. int filp_close(struct file *filp, fl_owner_t id)
  710. {
  711. int retval;
  712. if (!file_count(filp)) {
  713. printk(KERN_ERR "VFS: Close: file count is 0n");
  714. return 0;
  715. }
  716. retval = 0;
  717. if (filp->f_op && filp->f_op->flush) {
  718. lock_kernel();
  719. retval = filp->f_op->flush(filp);
  720. unlock_kernel();
  721. }
  722. dnotify_flush(filp, id);
  723. locks_remove_posix(filp, id);
  724. fput(filp);
  725. return retval;
  726. }
  727. /*
  728.  * Careful here! We test whether the file pointer is NULL before
  729.  * releasing the fd. This ensures that one clone task can't release
  730.  * an fd while another clone is opening it.
  731.  */
  732. asmlinkage long sys_close(unsigned int fd)
  733. {
  734. struct file * filp;
  735. struct files_struct *files = current->files;
  736. write_lock(&files->file_lock);
  737. if (fd >= files->max_fds)
  738. goto out_unlock;
  739. filp = files->fd[fd];
  740. if (!filp)
  741. goto out_unlock;
  742. files->fd[fd] = NULL;
  743. FD_CLR(fd, files->close_on_exec);
  744. __put_unused_fd(files, fd);
  745. write_unlock(&files->file_lock);
  746. return filp_close(filp, files);
  747. out_unlock:
  748. write_unlock(&files->file_lock);
  749. return -EBADF;
  750. }
  751. /*
  752.  * This routine simulates a hangup on the tty, to arrange that users
  753.  * are given clean terminals at login time.
  754.  */
  755. asmlinkage long sys_vhangup(void)
  756. {
  757. if (capable(CAP_SYS_TTY_CONFIG)) {
  758. tty_vhangup(current->tty);
  759. return 0;
  760. }
  761. return -EPERM;
  762. }
  763. /*
  764.  * Called when an inode is about to be open.
  765.  * We use this to disallow opening RW large files on 32bit systems if
  766.  * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
  767.  * on this flag in sys_open.
  768.  */
  769. int generic_file_open(struct inode * inode, struct file * filp)
  770. {
  771. if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS)
  772. return -EFBIG;
  773. return 0;
  774. }
  775. EXPORT_SYMBOL(generic_file_open);