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