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