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