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