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