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