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 #include <linux/mm.h>
20
21 #include <asm/segment.h>
22
23 extern void fcntl_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);
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);
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_fs_long((unsigned long *) ×->actime);
161 modtime = get_fs_long((unsigned long *) ×->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_access(const char * filename, int mode)
185 {
186 struct inode * inode;
187 int old_fsuid, old_fsgid;
188 int res;
189
190 if (mode != (mode & S_IRWXO))
191 return -EINVAL;
192 old_fsuid = current->fsuid;
193 old_fsgid = current->fsgid;
194 current->fsuid = current->uid;
195 current->fsgid = current->gid;
196 res = namei(filename,&inode);
197 if (!res) {
198 res = permission(inode, mode);
199 iput(inode);
200 }
201 current->fsuid = old_fsuid;
202 current->fsgid = old_fsgid;
203 return res;
204 }
205
206 asmlinkage int sys_chdir(const char * filename)
207 {
208 struct inode * inode;
209 int error;
210
211 error = namei(filename,&inode);
212 if (error)
213 return error;
214 if (!S_ISDIR(inode->i_mode)) {
215 iput(inode);
216 return -ENOTDIR;
217 }
218 if ((error = permission(inode,MAY_EXEC)) != 0) {
219 iput(inode);
220 return error;
221 }
222 iput(current->fs->pwd);
223 current->fs->pwd = inode;
224 return (0);
225 }
226
227 asmlinkage int sys_fchdir(unsigned int fd)
228 {
229 struct inode * inode;
230 struct file * file;
231 int error;
232
233 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
234 return -EBADF;
235 if (!(inode = file->f_inode))
236 return -ENOENT;
237 if (!S_ISDIR(inode->i_mode))
238 return -ENOTDIR;
239 if ((error = permission(inode,MAY_EXEC)) != 0)
240 return error;
241 iput(current->fs->pwd);
242 current->fs->pwd = inode;
243 inode->i_count++;
244 return (0);
245 }
246
247 asmlinkage int sys_chroot(const char * filename)
248 {
249 struct inode * inode;
250 int error;
251
252 error = namei(filename,&inode);
253 if (error)
254 return error;
255 if (!S_ISDIR(inode->i_mode)) {
256 iput(inode);
257 return -ENOTDIR;
258 }
259 if (!fsuser()) {
260 iput(inode);
261 return -EPERM;
262 }
263 iput(current->fs->root);
264 current->fs->root = inode;
265 return (0);
266 }
267
268 asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
269 {
270 struct inode * inode;
271 struct file * file;
272 struct iattr newattrs;
273
274 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
275 return -EBADF;
276 if (!(inode = file->f_inode))
277 return -ENOENT;
278 if (IS_RDONLY(inode))
279 return -EROFS;
280 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
281 return -EPERM;
282 if (mode == (mode_t) -1)
283 mode = inode->i_mode;
284 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
285 newattrs.ia_ctime = CURRENT_TIME;
286 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
287 inode->i_dirt = 1;
288 return notify_change(inode, &newattrs);
289 }
290
291 asmlinkage int sys_chmod(const char * filename, mode_t mode)
292 {
293 struct inode * inode;
294 int error;
295 struct iattr newattrs;
296
297 error = namei(filename,&inode);
298 if (error)
299 return error;
300 if (IS_RDONLY(inode)) {
301 iput(inode);
302 return -EROFS;
303 }
304 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
305 iput(inode);
306 return -EPERM;
307 }
308 if (mode == (mode_t) -1)
309 mode = inode->i_mode;
310 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
311 newattrs.ia_ctime = CURRENT_TIME;
312 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
313 inode->i_dirt = 1;
314 error = notify_change(inode, &newattrs);
315 iput(inode);
316 return error;
317 }
318
319 asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
320 {
321 struct inode * inode;
322 struct file * file;
323 struct iattr newattrs;
324
325 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
326 return -EBADF;
327 if (!(inode = file->f_inode))
328 return -ENOENT;
329 if (IS_RDONLY(inode))
330 return -EROFS;
331 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
332 return -EPERM;
333 if (user == (uid_t) -1)
334 user = inode->i_uid;
335 if (group == (gid_t) -1)
336 group = inode->i_gid;
337 newattrs.ia_mode = inode->i_mode;
338 newattrs.ia_uid = user;
339 newattrs.ia_gid = group;
340 newattrs.ia_ctime = CURRENT_TIME;
341 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
342
343
344
345 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
346 newattrs.ia_mode &= ~S_ISUID;
347 newattrs.ia_valid |= ATTR_MODE;
348 }
349
350
351
352 if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
353 newattrs.ia_mode &= ~S_ISGID;
354 newattrs.ia_valid |= ATTR_MODE;
355 }
356 inode->i_dirt = 1;
357 return notify_change(inode, &newattrs);
358 }
359
360 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
361 {
362 struct inode * inode;
363 int error;
364 struct iattr newattrs;
365
366 error = lnamei(filename,&inode);
367 if (error)
368 return error;
369 if (IS_RDONLY(inode)) {
370 iput(inode);
371 return -EROFS;
372 }
373 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) {
374 iput(inode);
375 return -EPERM;
376 }
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 error = notify_change(inode, &newattrs);
402 iput(inode);
403 return(error);
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420 int do_open(const char * filename,int flags,int mode)
421 {
422 struct inode * inode;
423 struct file * f;
424 int flag,error,fd;
425
426 for(fd=0; fd<NR_OPEN && fd<current->rlim[RLIMIT_NOFILE].rlim_cur; fd++)
427 if (!current->files->fd[fd])
428 break;
429 if (fd>=NR_OPEN || fd>=current->rlim[RLIMIT_NOFILE].rlim_cur)
430 return -EMFILE;
431 FD_CLR(fd,¤t->files->close_on_exec);
432 f = get_empty_filp();
433 if (!f)
434 return -ENFILE;
435 current->files->fd[fd] = f;
436 f->f_flags = flag = flags;
437 f->f_mode = (flag+1) & O_ACCMODE;
438 if (f->f_mode)
439 flag++;
440 if (flag & (O_TRUNC | O_CREAT))
441 flag |= 2;
442 error = open_namei(filename,flag,mode,&inode,NULL);
443 if (!error && (f->f_mode & 2)) {
444 error = get_write_access(inode);
445 if (error)
446 iput(inode);
447 }
448 if (error) {
449 current->files->fd[fd]=NULL;
450 f->f_count--;
451 return error;
452 }
453
454 f->f_inode = inode;
455 f->f_pos = 0;
456 f->f_reada = 0;
457 f->f_op = NULL;
458 if (inode->i_op)
459 f->f_op = inode->i_op->default_file_ops;
460 if (f->f_op && f->f_op->open) {
461 error = f->f_op->open(inode,f);
462 if (error) {
463 if (f->f_mode & 2) put_write_access(inode);
464 iput(inode);
465 f->f_count--;
466 current->files->fd[fd]=NULL;
467 return error;
468 }
469 }
470 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
471 return (fd);
472 }
473
474 asmlinkage int sys_open(const char * filename,int flags,int mode)
475 {
476 char * tmp;
477 int error;
478
479 error = getname(filename, &tmp);
480 if (error)
481 return error;
482 error = do_open(tmp,flags,mode);
483 putname(tmp);
484 return error;
485 }
486
487 asmlinkage int sys_creat(const char * pathname, int mode)
488 {
489 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
490 }
491
492 int close_fp(struct file *filp)
493 {
494 struct inode *inode;
495
496 if (filp->f_count == 0) {
497 printk("VFS: Close: file count is 0\n");
498 return 0;
499 }
500 inode = filp->f_inode;
501 if (inode)
502 fcntl_remove_locks(current, filp);
503 if (filp->f_count > 1) {
504 filp->f_count--;
505 return 0;
506 }
507 if (filp->f_op && filp->f_op->release)
508 filp->f_op->release(inode,filp);
509 filp->f_count--;
510 filp->f_inode = NULL;
511 if (filp->f_mode & 2) put_write_access(inode);
512 iput(inode);
513 return 0;
514 }
515
516 asmlinkage int sys_close(unsigned int fd)
517 {
518 struct file * filp;
519
520 if (fd >= NR_OPEN)
521 return -EBADF;
522 FD_CLR(fd, ¤t->files->close_on_exec);
523 if (!(filp = current->files->fd[fd]))
524 return -EBADF;
525 current->files->fd[fd] = NULL;
526 return (close_fp (filp));
527 }
528
529
530
531
532
533 asmlinkage int sys_vhangup(void)
534 {
535 if (!suser())
536 return -EPERM;
537
538 if (current->tty)
539 tty_vhangup(current->tty);
540 return 0;
541 }