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

嵌入式Linux

开发平台:

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