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