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