This source file includes following definitions.
- sys_statfs
- sys_fstatfs
- do_truncate
- sys_truncate
- sys_ftruncate
- sys_utime
- sys_utimes
- sys_access
- sys_chdir
- sys_fchdir
- sys_chroot
- sys_fchmod
- sys_chmod
- sys_fchown
- sys_chown
- do_open
- sys_open
- sys_creat
- close_fp
- sys_close
- sys_vhangup
1
2
3
4
5
6
7 #include <linux/vfs.h>
8 #include <linux/types.h>
9 #include <linux/utime.h>
10 #include <linux/errno.h>
11 #include <linux/fcntl.h>
12 #include <linux/stat.h>
13 #include <linux/string.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/signal.h>
17 #include <linux/tty.h>
18 #include <linux/time.h>
19 #include <linux/mm.h>
20
21 #include <asm/segment.h>
22
23 extern void locks_remove_locks(struct task_struct *, struct file *);
24
25 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
26 {
27 struct inode * inode;
28 int error;
29
30 error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
31 if (error)
32 return error;
33 error = namei(path,&inode);
34 if (error)
35 return error;
36 if (!inode->i_sb->s_op->statfs) {
37 iput(inode);
38 return -ENOSYS;
39 }
40 inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
41 iput(inode);
42 return 0;
43 }
44
45 asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
46 {
47 struct inode * inode;
48 struct file * file;
49 int error;
50
51 error = verify_area(VERIFY_WRITE, buf, sizeof(struct statfs));
52 if (error)
53 return error;
54 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
55 return -EBADF;
56 if (!(inode = file->f_inode))
57 return -ENOENT;
58 if (!inode->i_sb->s_op->statfs)
59 return -ENOSYS;
60 inode->i_sb->s_op->statfs(inode->i_sb, buf, sizeof(struct statfs));
61 return 0;
62 }
63
64 int do_truncate(struct inode *inode, unsigned long length)
65 {
66 int error;
67 struct iattr newattrs;
68
69 down(&inode->i_sem);
70 newattrs.ia_size = length;
71 newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
72 error = notify_change(inode, &newattrs);
73 if (!error) {
74
75 vmtruncate(inode, length);
76 if (inode->i_op && inode->i_op->truncate)
77 inode->i_op->truncate(inode);
78 }
79 up(&inode->i_sem);
80 return error;
81 }
82
83 asmlinkage int sys_truncate(const char * path, unsigned long length)
84 {
85 struct inode * inode;
86 int error;
87
88 error = namei(path,&inode);
89 if (error)
90 return error;
91 if (S_ISDIR(inode->i_mode)) {
92 iput(inode);
93 return -EACCES;
94 }
95 if ((error = permission(inode,MAY_WRITE)) != 0) {
96 iput(inode);
97 return error;
98 }
99 if (IS_RDONLY(inode)) {
100 iput(inode);
101 return -EROFS;
102 }
103 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
104 iput(inode);
105 return -EPERM;
106 }
107 error = get_write_access(inode);
108 if (error) {
109 iput(inode);
110 return error;
111 }
112 error = do_truncate(inode, length);
113 put_write_access(inode);
114 iput(inode);
115 return error;
116 }
117
118 asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
119 {
120 struct inode * inode;
121 struct file * file;
122
123 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
124 return -EBADF;
125 if (!(inode = file->f_inode))
126 return -ENOENT;
127 if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
128 return -EACCES;
129 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
130 return -EPERM;
131 return do_truncate(inode, length);
132 }
133
134 #ifndef __alpha__
135
136
137
138
139
140
141
142
143
144
145
146
147 asmlinkage int sys_utime(char * filename, struct utimbuf * times)
148 {
149 int error;
150 struct inode * inode;
151 struct iattr newattrs;
152
153 error = namei(filename,&inode);
154 if (error)
155 return error;
156 if (IS_RDONLY(inode)) {
157 iput(inode);
158 return -EROFS;
159 }
160
161 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
162 if (times) {
163 error = verify_area(VERIFY_READ, times, sizeof(*times));
164 if (error) {
165 iput(inode);
166 return error;
167 }
168 newattrs.ia_atime = get_user(×->actime);
169 newattrs.ia_mtime = get_user(×->modtime);
170 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
171 } else {
172 if ((error = permission(inode,MAY_WRITE)) != 0) {
173 iput(inode);
174 return error;
175 }
176 }
177 error = notify_change(inode, &newattrs);
178 iput(inode);
179 return error;
180 }
181
182 #endif
183
184
185
186
187
188 asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
189 {
190 int error;
191 struct inode * inode;
192 struct iattr newattrs;
193
194 error = namei(filename,&inode);
195 if (error)
196 return error;
197 if (IS_RDONLY(inode)) {
198 iput(inode);
199 return -EROFS;
200 }
201
202 newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
203 if (utimes) {
204 struct timeval times[2];
205 error = verify_area(VERIFY_READ, utimes, sizeof(times));
206 if (error) {
207 iput(inode);
208 return error;
209 }
210 memcpy_fromfs(×, utimes, sizeof(times));
211 newattrs.ia_atime = times[0].tv_sec;
212 newattrs.ia_mtime = times[1].tv_sec;
213 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
214 } else {
215 if ((error = permission(inode,MAY_WRITE)) != 0) {
216 iput(inode);
217 return error;
218 }
219 }
220 error = notify_change(inode, &newattrs);
221 iput(inode);
222 return error;
223 }
224
225
226
227
228
229 asmlinkage int sys_access(const char * filename, int mode)
230 {
231 struct inode * inode;
232 int old_fsuid, old_fsgid;
233 int res;
234
235 if (mode != (mode & S_IRWXO))
236 return -EINVAL;
237 old_fsuid = current->fsuid;
238 old_fsgid = current->fsgid;
239 current->fsuid = current->uid;
240 current->fsgid = current->gid;
241 res = namei(filename,&inode);
242 if (!res) {
243 res = permission(inode, mode);
244 iput(inode);
245 }
246 current->fsuid = old_fsuid;
247 current->fsgid = old_fsgid;
248 return res;
249 }
250
251 asmlinkage int sys_chdir(const char * filename)
252 {
253 struct inode * inode;
254 int error;
255
256 error = namei(filename,&inode);
257 if (error)
258 return error;
259 if (!S_ISDIR(inode->i_mode)) {
260 iput(inode);
261 return -ENOTDIR;
262 }
263 if ((error = permission(inode,MAY_EXEC)) != 0) {
264 iput(inode);
265 return error;
266 }
267 iput(current->fs->pwd);
268 current->fs->pwd = inode;
269 return (0);
270 }
271
272 asmlinkage int sys_fchdir(unsigned int fd)
273 {
274 struct inode * inode;
275 struct file * file;
276 int error;
277
278 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
279 return -EBADF;
280 if (!(inode = file->f_inode))
281 return -ENOENT;
282 if (!S_ISDIR(inode->i_mode))
283 return -ENOTDIR;
284 if ((error = permission(inode,MAY_EXEC)) != 0)
285 return error;
286 iput(current->fs->pwd);
287 current->fs->pwd = inode;
288 inode->i_count++;
289 return (0);
290 }
291
292 asmlinkage int sys_chroot(const char * filename)
293 {
294 struct inode * inode;
295 int error;
296
297 error = namei(filename,&inode);
298 if (error)
299 return error;
300 if (!S_ISDIR(inode->i_mode)) {
301 iput(inode);
302 return -ENOTDIR;
303 }
304 if (!fsuser()) {
305 iput(inode);
306 return -EPERM;
307 }
308 iput(current->fs->root);
309 current->fs->root = inode;
310 return (0);
311 }
312
313 asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
314 {
315 struct inode * inode;
316 struct file * file;
317 struct iattr newattrs;
318
319 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
320 return -EBADF;
321 if (!(inode = file->f_inode))
322 return -ENOENT;
323 if (IS_RDONLY(inode))
324 return -EROFS;
325 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
326 return -EPERM;
327 if (mode == (mode_t) -1)
328 mode = inode->i_mode;
329 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
330 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
331 inode->i_dirt = 1;
332 return notify_change(inode, &newattrs);
333 }
334
335 asmlinkage int sys_chmod(const char * filename, mode_t mode)
336 {
337 struct inode * inode;
338 int error;
339 struct iattr newattrs;
340
341 error = namei(filename,&inode);
342 if (error)
343 return error;
344 if (IS_RDONLY(inode)) {
345 iput(inode);
346 return -EROFS;
347 }
348 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
349 iput(inode);
350 return -EPERM;
351 }
352 if (mode == (mode_t) -1)
353 mode = inode->i_mode;
354 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
355 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
356 inode->i_dirt = 1;
357 error = notify_change(inode, &newattrs);
358 iput(inode);
359 return error;
360 }
361
362 asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
363 {
364 struct inode * inode;
365 struct file * file;
366 struct iattr newattrs;
367 int error;
368
369 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
370 return -EBADF;
371 if (!(inode = file->f_inode))
372 return -ENOENT;
373 if (IS_RDONLY(inode))
374 return -EROFS;
375 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
376 return -EPERM;
377 if (user == (uid_t) -1)
378 user = inode->i_uid;
379 if (group == (gid_t) -1)
380 group = inode->i_gid;
381 newattrs.ia_mode = inode->i_mode;
382 newattrs.ia_uid = user;
383 newattrs.ia_gid = group;
384 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
385
386
387
388 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
389 newattrs.ia_mode &= ~S_ISUID;
390 newattrs.ia_valid |= ATTR_MODE;
391 }
392
393
394
395 if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
396 newattrs.ia_mode &= ~S_ISGID;
397 newattrs.ia_valid |= ATTR_MODE;
398 }
399 inode->i_dirt = 1;
400 if (inode->i_sb && inode->i_sb->dq_op) {
401 inode->i_sb->dq_op->initialize(inode, -1);
402 if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
403 return -EDQUOT;
404 error = notify_change(inode, &newattrs);
405 if (error)
406 inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
407 } else
408 error = notify_change(inode, &newattrs);
409 return error;
410 }
411
412 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
413 {
414 struct inode * inode;
415 int error;
416 struct iattr newattrs;
417
418 error = lnamei(filename,&inode);
419 if (error)
420 return error;
421 if (IS_RDONLY(inode)) {
422 iput(inode);
423 return -EROFS;
424 }
425 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
426 iput(inode);
427 return -EPERM;
428 }
429 if (user == (uid_t) -1)
430 user = inode->i_uid;
431 if (group == (gid_t) -1)
432 group = inode->i_gid;
433 newattrs.ia_mode = inode->i_mode;
434 newattrs.ia_uid = user;
435 newattrs.ia_gid = group;
436 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
437
438
439
440 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
441 newattrs.ia_mode &= ~S_ISUID;
442 newattrs.ia_valid |= ATTR_MODE;
443 }
444
445
446
447 if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
448 newattrs.ia_mode &= ~S_ISGID;
449 newattrs.ia_valid |= ATTR_MODE;
450 }
451 inode->i_dirt = 1;
452 if (inode->i_sb->dq_op) {
453 inode->i_sb->dq_op->initialize(inode, -1);
454 if (inode->i_sb->dq_op->transfer(inode, &newattrs, 0))
455 return -EDQUOT;
456 error = notify_change(inode, &newattrs);
457 if (error)
458 inode->i_sb->dq_op->transfer(inode, &newattrs, 1);
459 } else
460 error = notify_change(inode, &newattrs);
461 iput(inode);
462 return(error);
463 }
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479 int do_open(const char * filename,int flags,int mode)
480 {
481 struct inode * inode;
482 struct file * f;
483 int flag,error,fd;
484
485 f = get_empty_filp();
486 if (!f)
487 return -ENFILE;
488 f->f_flags = flag = flags;
489 f->f_mode = (flag+1) & O_ACCMODE;
490 if (f->f_mode)
491 flag++;
492 if (flag & (O_TRUNC | O_CREAT))
493 flag |= 2;
494 error = open_namei(filename,flag,mode,&inode,NULL);
495 if (error)
496 goto cleanup_file;
497 if (f->f_mode & FMODE_WRITE) {
498 error = get_write_access(inode);
499 if (error)
500 goto cleanup_inode;
501 }
502
503 f->f_inode = inode;
504 f->f_pos = 0;
505 f->f_reada = 0;
506 f->f_op = NULL;
507 if (inode->i_op)
508 f->f_op = inode->i_op->default_file_ops;
509 if (f->f_op && f->f_op->open) {
510 error = f->f_op->open(inode,f);
511 if (error)
512 goto cleanup_all;
513 }
514 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
515
516
517
518
519
520
521 for(fd = 0; fd < NR_OPEN && fd < current->rlim[RLIMIT_NOFILE].rlim_cur; fd++) {
522 if (!current->files->fd[fd]) {
523 current->files->fd[fd] = f;
524 FD_CLR(fd,¤t->files->close_on_exec);
525 return fd;
526 }
527 }
528 error = -EMFILE;
529 if (f->f_op && f->f_op->release)
530 f->f_op->release(inode,f);
531 cleanup_all:
532 if (f->f_mode & FMODE_WRITE)
533 put_write_access(inode);
534 cleanup_inode:
535 iput(inode);
536 cleanup_file:
537 f->f_count--;
538 return error;
539 }
540
541 asmlinkage int sys_open(const char * filename,int flags,int mode)
542 {
543 char * tmp;
544 int error;
545
546 error = getname(filename, &tmp);
547 if (error)
548 return error;
549 error = do_open(tmp,flags,mode);
550 putname(tmp);
551 return error;
552 }
553
554 #ifndef __alpha__
555
556
557
558
559
560 asmlinkage int sys_creat(const char * pathname, int mode)
561 {
562 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
563 }
564
565 #endif
566
567 int close_fp(struct file *filp)
568 {
569 struct inode *inode;
570
571 if (filp->f_count == 0) {
572 printk("VFS: Close: file count is 0\n");
573 return 0;
574 }
575 inode = filp->f_inode;
576 if (inode)
577 locks_remove_locks(current, filp);
578 if (filp->f_count > 1) {
579 filp->f_count--;
580 return 0;
581 }
582 if (filp->f_op && filp->f_op->release)
583 filp->f_op->release(inode,filp);
584 filp->f_count--;
585 filp->f_inode = NULL;
586 if (filp->f_mode & FMODE_WRITE)
587 put_write_access(inode);
588 iput(inode);
589 return 0;
590 }
591
592 asmlinkage int sys_close(unsigned int fd)
593 {
594 struct file * filp;
595
596 if (fd >= NR_OPEN)
597 return -EBADF;
598 FD_CLR(fd, ¤t->files->close_on_exec);
599 if (!(filp = current->files->fd[fd]))
600 return -EBADF;
601 current->files->fd[fd] = NULL;
602 return (close_fp (filp));
603 }
604
605
606
607
608
609 asmlinkage int sys_vhangup(void)
610 {
611 if (!suser())
612 return -EPERM;
613
614 if (current->tty)
615 tty_vhangup(current->tty);
616 return 0;
617 }