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