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