1
2
3
4
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/namei.h>
18#include <linux/backing-dev.h>
19#include <linux/security.h>
20#include <linux/mount.h>
21#include <linux/vfs.h>
22#include <asm/uaccess.h>
23#include <linux/fs.h>
24#include <linux/pagemap.h>
25
26int vfs_statfs(struct super_block *sb, struct kstatfs *buf)
27{
28 int retval = -ENODEV;
29
30 if (sb) {
31 retval = -ENOSYS;
32 if (sb->s_op->statfs) {
33 memset(buf, 0, sizeof(*buf));
34 retval = security_sb_statfs(sb);
35 if (retval)
36 return retval;
37 retval = sb->s_op->statfs(sb, buf);
38 if (retval == 0 && buf->f_frsize == 0)
39 buf->f_frsize = buf->f_bsize;
40 }
41 }
42 return retval;
43}
44
45EXPORT_SYMBOL(vfs_statfs);
46
47static int vfs_statfs_native(struct super_block *sb, struct statfs *buf)
48{
49 struct kstatfs st;
50 int retval;
51
52 retval = vfs_statfs(sb, &st);
53 if (retval)
54 return retval;
55
56 if (sizeof(*buf) == sizeof(st))
57 memcpy(buf, &st, sizeof(st));
58 else {
59 if (sizeof buf->f_blocks == 4) {
60 if ((st.f_blocks | st.f_bfree |
61 st.f_bavail | st.f_files | st.f_ffree) &
62 0xffffffff00000000ULL)
63 return -EOVERFLOW;
64 }
65
66 buf->f_type = st.f_type;
67 buf->f_bsize = st.f_bsize;
68 buf->f_blocks = st.f_blocks;
69 buf->f_bfree = st.f_bfree;
70 buf->f_bavail = st.f_bavail;
71 buf->f_files = st.f_files;
72 buf->f_ffree = st.f_ffree;
73 buf->f_fsid = st.f_fsid;
74 buf->f_namelen = st.f_namelen;
75 buf->f_frsize = st.f_frsize;
76 memset(buf->f_spare, 0, sizeof(buf->f_spare));
77 }
78 return 0;
79}
80
81static int vfs_statfs64(struct super_block *sb, struct statfs64 *buf)
82{
83 struct kstatfs st;
84 int retval;
85
86 retval = vfs_statfs(sb, &st);
87 if (retval)
88 return retval;
89
90 if (sizeof(*buf) == sizeof(st))
91 memcpy(buf, &st, sizeof(st));
92 else {
93 buf->f_type = st.f_type;
94 buf->f_bsize = st.f_bsize;
95 buf->f_blocks = st.f_blocks;
96 buf->f_bfree = st.f_bfree;
97 buf->f_bavail = st.f_bavail;
98 buf->f_files = st.f_files;
99 buf->f_ffree = st.f_ffree;
100 buf->f_fsid = st.f_fsid;
101 buf->f_namelen = st.f_namelen;
102 buf->f_frsize = st.f_frsize;
103 memset(buf->f_spare, 0, sizeof(buf->f_spare));
104 }
105 return 0;
106}
107
108asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf)
109{
110 struct nameidata nd;
111 int error;
112
113 error = user_path_walk(path, &nd);
114 if (!error) {
115 struct statfs tmp;
116 error = vfs_statfs_native(nd.dentry->d_inode->i_sb, &tmp);
117 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
118 error = -EFAULT;
119 path_release(&nd);
120 }
121 return error;
122}
123
124
125asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf)
126{
127 struct nameidata nd;
128 long error;
129
130 if (sz != sizeof(*buf))
131 return -EINVAL;
132 error = user_path_walk(path, &nd);
133 if (!error) {
134 struct statfs64 tmp;
135 error = vfs_statfs64(nd.dentry->d_inode->i_sb, &tmp);
136 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
137 error = -EFAULT;
138 path_release(&nd);
139 }
140 return error;
141}
142
143
144asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf)
145{
146 struct file * file;
147 struct statfs tmp;
148 int error;
149
150 error = -EBADF;
151 file = fget(fd);
152 if (!file)
153 goto out;
154 error = vfs_statfs_native(file->f_dentry->d_inode->i_sb, &tmp);
155 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
156 error = -EFAULT;
157 fput(file);
158out:
159 return error;
160}
161
162asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user *buf)
163{
164 struct file * file;
165 struct statfs64 tmp;
166 int error;
167
168 if (sz != sizeof(*buf))
169 return -EINVAL;
170
171 error = -EBADF;
172 file = fget(fd);
173 if (!file)
174 goto out;
175 error = vfs_statfs64(file->f_dentry->d_inode->i_sb, &tmp);
176 if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
177 error = -EFAULT;
178 fput(file);
179out:
180 return error;
181}
182
183int do_truncate(struct dentry *dentry, loff_t length)
184{
185 int err;
186 struct iattr newattrs;
187
188
189 if (length < 0)
190 return -EINVAL;
191
192 newattrs.ia_size = length;
193 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
194 down(&dentry->d_inode->i_sem);
195 err = notify_change(dentry, &newattrs);
196 up(&dentry->d_inode->i_sem);
197 return err;
198}
199
200static inline long do_sys_truncate(const char __user * path, loff_t length)
201{
202 struct nameidata nd;
203 struct inode * inode;
204 int error;
205
206 error = -EINVAL;
207 if (length < 0)
208 goto out;
209
210 error = user_path_walk(path, &nd);
211 if (error)
212 goto out;
213 inode = nd.dentry->d_inode;
214
215
216 error = -EISDIR;
217 if (S_ISDIR(inode->i_mode))
218 goto dput_and_out;
219
220 error = -EINVAL;
221 if (!S_ISREG(inode->i_mode))
222 goto dput_and_out;
223
224 error = permission(inode,MAY_WRITE,&nd);
225 if (error)
226 goto dput_and_out;
227
228 error = -EROFS;
229 if (IS_RDONLY(inode))
230 goto dput_and_out;
231
232 error = -EPERM;
233 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
234 goto dput_and_out;
235
236
237
238
239 error = break_lease(inode, FMODE_WRITE);
240 if (error)
241 goto dput_and_out;
242
243 error = get_write_access(inode);
244 if (error)
245 goto dput_and_out;
246
247 error = locks_verify_truncate(inode, NULL, length);
248 if (!error) {
249 DQUOT_INIT(inode);
250 error = do_truncate(nd.dentry, length);
251 }
252 put_write_access(inode);
253
254dput_and_out:
255 path_release(&nd);
256out:
257 return error;
258}
259
260asmlinkage long sys_truncate(const char __user * path, unsigned long length)
261{
262
263 return do_sys_truncate(path, (long)length);
264}
265
266static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
267{
268 struct inode * inode;
269 struct dentry *dentry;
270 struct file * file;
271 int error;
272
273 error = -EINVAL;
274 if (length < 0)
275 goto out;
276 error = -EBADF;
277 file = fget(fd);
278 if (!file)
279 goto out;
280
281
282 if (file->f_flags & O_LARGEFILE)
283 small = 0;
284
285 dentry = file->f_dentry;
286 inode = dentry->d_inode;
287 error = -EINVAL;
288 if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
289 goto out_putf;
290
291 error = -EINVAL;
292
293 if (small && length > MAX_NON_LFS)
294 goto out_putf;
295
296 error = -EPERM;
297 if (IS_APPEND(inode))
298 goto out_putf;
299
300 error = locks_verify_truncate(inode, file, length);
301 if (!error)
302 error = do_truncate(dentry, length);
303out_putf:
304 fput(file);
305out:
306 return error;
307}
308
309asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
310{
311 return do_sys_ftruncate(fd, length, 1);
312}
313
314
315#if BITS_PER_LONG == 32
316asmlinkage long sys_truncate64(const char __user * path, loff_t length)
317{
318 return do_sys_truncate(path, length);
319}
320
321asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
322{
323 return do_sys_ftruncate(fd, length, 0);
324}
325#endif
326
327#if !(defined(__alpha__) || defined(__ia64__))
328
329
330
331
332
333
334
335
336
337
338
339
340asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
341{
342 int error;
343 struct nameidata nd;
344 struct inode * inode;
345 struct iattr newattrs;
346
347 error = user_path_walk(filename, &nd);
348 if (error)
349 goto out;
350 inode = nd.dentry->d_inode;
351
352 error = -EROFS;
353 if (IS_RDONLY(inode))
354 goto dput_and_out;
355
356
357 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
358 if (times) {
359 error = -EPERM;
360 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
361 goto dput_and_out;
362
363 error = get_user(newattrs.ia_atime.tv_sec, ×->actime);
364 newattrs.ia_atime.tv_nsec = 0;
365 if (!error)
366 error = get_user(newattrs.ia_mtime.tv_sec, ×->modtime);
367 newattrs.ia_mtime.tv_nsec = 0;
368 if (error)
369 goto dput_and_out;
370
371 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
372 } else {
373 error = -EACCES;
374 if (IS_IMMUTABLE(inode))
375 goto dput_and_out;
376
377 if (current->fsuid != inode->i_uid &&
378 (error = permission(inode,MAY_WRITE,&nd)) != 0)
379 goto dput_and_out;
380 }
381 down(&inode->i_sem);
382 error = notify_change(nd.dentry, &newattrs);
383 up(&inode->i_sem);
384dput_and_out:
385 path_release(&nd);
386out:
387 return error;
388}
389
390#endif
391
392
393
394
395
396long do_utimes(char __user * filename, struct timeval * times)
397{
398 int error;
399 struct nameidata nd;
400 struct inode * inode;
401 struct iattr newattrs;
402
403 error = user_path_walk(filename, &nd);
404
405 if (error)
406 goto out;
407 inode = nd.dentry->d_inode;
408
409 error = -EROFS;
410 if (IS_RDONLY(inode))
411 goto dput_and_out;
412
413
414 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
415 if (times) {
416 error = -EPERM;
417 if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
418 goto dput_and_out;
419
420 newattrs.ia_atime.tv_sec = times[0].tv_sec;
421 newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000;
422 newattrs.ia_mtime.tv_sec = times[1].tv_sec;
423 newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000;
424 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
425 } else {
426 error = -EACCES;
427 if (IS_IMMUTABLE(inode))
428 goto dput_and_out;
429
430 if (current->fsuid != inode->i_uid &&
431 (error = permission(inode,MAY_WRITE,&nd)) != 0)
432 goto dput_and_out;
433 }
434 down(&inode->i_sem);
435 error = notify_change(nd.dentry, &newattrs);
436 up(&inode->i_sem);
437dput_and_out:
438 path_release(&nd);
439out:
440 return error;
441}
442
443asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utimes)
444{
445 struct timeval times[2];
446
447 if (utimes && copy_from_user(×, utimes, sizeof(times)))
448 return -EFAULT;
449 return do_utimes(filename, utimes ? times : NULL);
450}
451
452
453
454
455
456
457
458asmlinkage long sys_access(const char __user * filename, int mode)
459{
460 struct nameidata nd;
461 int old_fsuid, old_fsgid;
462 kernel_cap_t old_cap;
463 int res;
464
465 if (mode & ~S_IRWXO)
466 return -EINVAL;
467
468 old_fsuid = current->fsuid;
469 old_fsgid = current->fsgid;
470 old_cap = current->cap_effective;
471
472 current->fsuid = current->uid;
473 current->fsgid = current->gid;
474
475
476
477
478
479
480
481
482
483 if (current->uid)
484 cap_clear(current->cap_effective);
485 else
486 current->cap_effective = current->cap_permitted;
487
488 res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
489 if (!res) {
490 res = permission(nd.dentry->d_inode, mode, &nd);
491
492 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
493 && !special_file(nd.dentry->d_inode->i_mode))
494 res = -EROFS;
495 path_release(&nd);
496 }
497
498 current->fsuid = old_fsuid;
499 current->fsgid = old_fsgid;
500 current->cap_effective = old_cap;
501
502 return res;
503}
504
505asmlinkage long sys_chdir(const char __user * filename)
506{
507 struct nameidata nd;
508 int error;
509
510 error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
511 if (error)
512 goto out;
513
514 error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
515 if (error)
516 goto dput_and_out;
517
518 set_fs_pwd(current->fs, nd.mnt, nd.dentry);
519
520dput_and_out:
521 path_release(&nd);
522out:
523 return error;
524}
525
526asmlinkage long sys_fchdir(unsigned int fd)
527{
528 struct file *file;
529 struct dentry *dentry;
530 struct inode *inode;
531 struct vfsmount *mnt;
532 int error;
533
534 error = -EBADF;
535 file = fget(fd);
536 if (!file)
537 goto out;
538
539 dentry = file->f_dentry;
540 mnt = file->f_vfsmnt;
541 inode = dentry->d_inode;
542
543 error = -ENOTDIR;
544 if (!S_ISDIR(inode->i_mode))
545 goto out_putf;
546
547 error = permission(inode, MAY_EXEC, NULL);
548 if (!error)
549 set_fs_pwd(current->fs, mnt, dentry);
550out_putf:
551 fput(file);
552out:
553 return error;
554}
555
556asmlinkage long sys_chroot(const char __user * filename)
557{
558 struct nameidata nd;
559 int error;
560
561 error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
562 if (error)
563 goto out;
564
565 error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
566 if (error)
567 goto dput_and_out;
568
569 error = -EPERM;
570 if (!capable(CAP_SYS_CHROOT))
571 goto dput_and_out;
572
573 set_fs_root(current->fs, nd.mnt, nd.dentry);
574 set_fs_altroot();
575 error = 0;
576dput_and_out:
577 path_release(&nd);
578out:
579 return error;
580}
581
582asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
583{
584 struct inode * inode;
585 struct dentry * dentry;
586 struct file * file;
587 int err = -EBADF;
588 struct iattr newattrs;
589
590 file = fget(fd);
591 if (!file)
592 goto out;
593
594 dentry = file->f_dentry;
595 inode = dentry->d_inode;
596
597 err = -EROFS;
598 if (IS_RDONLY(inode))
599 goto out_putf;
600 err = -EPERM;
601 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
602 goto out_putf;
603 down(&inode->i_sem);
604 if (mode == (mode_t) -1)
605 mode = inode->i_mode;
606 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
607 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
608 err = notify_change(dentry, &newattrs);
609 up(&inode->i_sem);
610
611out_putf:
612 fput(file);
613out:
614 return err;
615}
616
617asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
618{
619 struct nameidata nd;
620 struct inode * inode;
621 int error;
622 struct iattr newattrs;
623
624 error = user_path_walk(filename, &nd);
625 if (error)
626 goto out;
627 inode = nd.dentry->d_inode;
628
629 error = -EROFS;
630 if (IS_RDONLY(inode))
631 goto dput_and_out;
632
633 error = -EPERM;
634 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
635 goto dput_and_out;
636
637 down(&inode->i_sem);
638 if (mode == (mode_t) -1)
639 mode = inode->i_mode;
640 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
641 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
642 error = notify_change(nd.dentry, &newattrs);
643 up(&inode->i_sem);
644
645dput_and_out:
646 path_release(&nd);
647out:
648 return error;
649}
650
651static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
652{
653 struct inode * inode;
654 int error;
655 struct iattr newattrs;
656
657 error = -ENOENT;
658 if (!(inode = dentry->d_inode)) {
659 printk(KERN_ERR "chown_common: NULL inode\n");
660 goto out;
661 }
662 error = -EROFS;
663 if (IS_RDONLY(inode))
664 goto out;
665 error = -EPERM;
666 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
667 goto out;
668 newattrs.ia_valid = ATTR_CTIME;
669 if (user != (uid_t) -1) {
670 newattrs.ia_valid |= ATTR_UID;
671 newattrs.ia_uid = user;
672 }
673 if (group != (gid_t) -1) {
674 newattrs.ia_valid |= ATTR_GID;
675 newattrs.ia_gid = group;
676 }
677 if (!S_ISDIR(inode->i_mode))
678 newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
679 down(&inode->i_sem);
680 error = notify_change(dentry, &newattrs);
681 up(&inode->i_sem);
682out:
683 return error;
684}
685
686asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
687{
688 struct nameidata nd;
689 int error;
690
691 error = user_path_walk(filename, &nd);
692 if (!error) {
693 error = chown_common(nd.dentry, user, group);
694 path_release(&nd);
695 }
696 return error;
697}
698
699asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
700{
701 struct nameidata nd;
702 int error;
703
704 error = user_path_walk_link(filename, &nd);
705 if (!error) {
706 error = chown_common(nd.dentry, user, group);
707 path_release(&nd);
708 }
709 return error;
710}
711
712
713asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
714{
715 struct file * file;
716 int error = -EBADF;
717
718 file = fget(fd);
719 if (file) {
720 error = chown_common(file->f_dentry, user, group);
721 fput(file);
722 }
723 return error;
724}
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740struct file *filp_open(const char * filename, int flags, int mode)
741{
742 int namei_flags, error;
743 struct nameidata nd;
744
745 namei_flags = flags;
746 if ((namei_flags+1) & O_ACCMODE)
747 namei_flags++;
748 if (namei_flags & O_TRUNC)
749 namei_flags |= 2;
750
751 error = open_namei(filename, namei_flags, mode, &nd);
752 if (!error)
753 return dentry_open(nd.dentry, nd.mnt, flags);
754
755 return ERR_PTR(error);
756}
757
758EXPORT_SYMBOL(filp_open);
759
760struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
761{
762 struct file * f;
763 struct inode *inode;
764 int error;
765
766 error = -ENFILE;
767 f = get_empty_filp();
768 if (!f)
769 goto cleanup_dentry;
770 f->f_flags = flags;
771 f->f_mode = (flags+1) & O_ACCMODE;
772 inode = dentry->d_inode;
773 if (f->f_mode & FMODE_WRITE) {
774 error = get_write_access(inode);
775 if (error)
776 goto cleanup_file;
777 }
778
779 file_ra_state_init(&f->f_ra, inode->i_mapping);
780 f->f_dentry = dentry;
781 f->f_vfsmnt = mnt;
782 f->f_pos = 0;
783 f->f_op = fops_get(inode->i_fop);
784 file_move(f, &inode->i_sb->s_files);
785
786 if (f->f_op && f->f_op->open) {
787 error = f->f_op->open(inode,f);
788 if (error)
789 goto cleanup_all;
790 }
791 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
792
793
794 if (f->f_flags & O_DIRECT) {
795 if (!inode->i_mapping || !inode->i_mapping->a_ops ||
796 !inode->i_mapping->a_ops->direct_IO) {
797 fput(f);
798 f = ERR_PTR(-EINVAL);
799 }
800 }
801
802 return f;
803
804cleanup_all:
805 fops_put(f->f_op);
806 if (f->f_mode & FMODE_WRITE)
807 put_write_access(inode);
808 file_kill(f);
809 f->f_dentry = NULL;
810 f->f_vfsmnt = NULL;
811cleanup_file:
812 put_filp(f);
813cleanup_dentry:
814 dput(dentry);
815 mntput(mnt);
816 return ERR_PTR(error);
817}
818
819EXPORT_SYMBOL(dentry_open);
820
821
822
823
824int get_unused_fd(void)
825{
826 struct files_struct * files = current->files;
827 int fd, error;
828
829 error = -EMFILE;
830 spin_lock(&files->file_lock);
831
832repeat:
833 fd = find_next_zero_bit(files->open_fds->fds_bits,
834 files->max_fdset,
835 files->next_fd);
836
837
838
839
840
841 if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
842 goto out;
843
844
845 if (fd >= files->max_fdset) {
846 error = expand_fdset(files, fd);
847 if (!error) {
848 error = -EMFILE;
849 goto repeat;
850 }
851 goto out;
852 }
853
854
855
856
857 if (fd >= files->max_fds) {
858 error = expand_fd_array(files, fd);
859 if (!error) {
860 error = -EMFILE;
861 goto repeat;
862 }
863 goto out;
864 }
865
866 FD_SET(fd, files->open_fds);
867 FD_CLR(fd, files->close_on_exec);
868 files->next_fd = fd + 1;
869#if 1
870
871 if (files->fd[fd] != NULL) {
872 printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
873 files->fd[fd] = NULL;
874 }
875#endif
876 error = fd;
877
878out:
879 spin_unlock(&files->file_lock);
880 return error;
881}
882
883EXPORT_SYMBOL(get_unused_fd);
884
885static inline void __put_unused_fd(struct files_struct *files, unsigned int fd)
886{
887 __FD_CLR(fd, files->open_fds);
888 if (fd < files->next_fd)
889 files->next_fd = fd;
890}
891
892void put_unused_fd(unsigned int fd)
893{
894 struct files_struct *files = current->files;
895 spin_lock(&files->file_lock);
896 __put_unused_fd(files, fd);
897 spin_unlock(&files->file_lock);
898}
899
900EXPORT_SYMBOL(put_unused_fd);
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915void fd_install(unsigned int fd, struct file * file)
916{
917 struct files_struct *files = current->files;
918 spin_lock(&files->file_lock);
919 if (unlikely(files->fd[fd] != NULL))
920 BUG();
921 files->fd[fd] = file;
922 spin_unlock(&files->file_lock);
923}
924
925EXPORT_SYMBOL(fd_install);
926
927asmlinkage long sys_open(const char __user * filename, int flags, int mode)
928{
929 char * tmp;
930 int fd, error;
931
932#if BITS_PER_LONG != 32
933 flags |= O_LARGEFILE;
934#endif
935 tmp = getname(filename);
936 fd = PTR_ERR(tmp);
937 if (!IS_ERR(tmp)) {
938 fd = get_unused_fd();
939 if (fd >= 0) {
940 struct file *f = filp_open(tmp, flags, mode);
941 error = PTR_ERR(f);
942 if (IS_ERR(f))
943 goto out_error;
944 fd_install(fd, f);
945 }
946out:
947 putname(tmp);
948 }
949 return fd;
950
951out_error:
952 put_unused_fd(fd);
953 fd = error;
954 goto out;
955}
956
957#ifndef __alpha__
958
959
960
961
962
963asmlinkage long sys_creat(const char __user * pathname, int mode)
964{
965 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
966}
967
968#endif
969
970
971
972
973
974int filp_close(struct file *filp, fl_owner_t id)
975{
976 int retval;
977
978
979 retval = filp->f_error;
980 if (retval)
981 filp->f_error = 0;
982
983 if (!file_count(filp)) {
984 printk(KERN_ERR "VFS: Close: file count is 0\n");
985 return retval;
986 }
987
988 if (filp->f_op && filp->f_op->flush) {
989 int err = filp->f_op->flush(filp);
990 if (!retval)
991 retval = err;
992 }
993
994 dnotify_flush(filp, id);
995 locks_remove_posix(filp, id);
996 fput(filp);
997 return retval;
998}
999
1000EXPORT_SYMBOL(filp_close);
1001
1002
1003
1004
1005
1006
1007asmlinkage long sys_close(unsigned int fd)
1008{
1009 struct file * filp;
1010 struct files_struct *files = current->files;
1011
1012 spin_lock(&files->file_lock);
1013 if (fd >= files->max_fds)
1014 goto out_unlock;
1015 filp = files->fd[fd];
1016 if (!filp)
1017 goto out_unlock;
1018 files->fd[fd] = NULL;
1019 FD_CLR(fd, files->close_on_exec);
1020 __put_unused_fd(files, fd);
1021 spin_unlock(&files->file_lock);
1022 return filp_close(filp, files);
1023
1024out_unlock:
1025 spin_unlock(&files->file_lock);
1026 return -EBADF;
1027}
1028
1029EXPORT_SYMBOL(sys_close);
1030
1031
1032
1033
1034
1035asmlinkage long sys_vhangup(void)
1036{
1037 if (capable(CAP_SYS_TTY_CONFIG)) {
1038 tty_vhangup(current->tty);
1039 return 0;
1040 }
1041 return -EPERM;
1042}
1043
1044
1045
1046
1047
1048
1049
1050int generic_file_open(struct inode * inode, struct file * filp)
1051{
1052 if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
1053 return -EFBIG;
1054 return 0;
1055}
1056
1057EXPORT_SYMBOL(generic_file_open);
1058