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 (mode == (mode_t) -1)
281 mode = inode->i_mode;
282 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
283 newattrs.ia_ctime = CURRENT_TIME;
284 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
285 inode->i_dirt = 1;
286 return notify_change(inode, &newattrs);
287 }
288
289 asmlinkage int sys_chmod(const char * filename, mode_t mode)
290 {
291 struct inode * inode;
292 int error;
293 struct iattr newattrs;
294
295 error = namei(filename,&inode);
296 if (error)
297 return error;
298 if (IS_RDONLY(inode)) {
299 iput(inode);
300 return -EROFS;
301 }
302 if (mode == (mode_t) -1)
303 mode = inode->i_mode;
304 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
305 newattrs.ia_ctime = CURRENT_TIME;
306 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
307 inode->i_dirt = 1;
308 error = notify_change(inode, &newattrs);
309 iput(inode);
310 return error;
311 }
312
313 asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
314 {
315 struct inode * inode;
316 struct file * file;
317 struct iattr newattrs;
318
319 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
320 return -EBADF;
321 if (!(inode = file->f_inode))
322 return -ENOENT;
323 if (IS_RDONLY(inode))
324 return -EROFS;
325 if (user == (uid_t) -1)
326 user = inode->i_uid;
327 if (group == (gid_t) -1)
328 group = inode->i_gid;
329 newattrs.ia_mode = inode->i_mode;
330 newattrs.ia_uid = user;
331 newattrs.ia_gid = group;
332 newattrs.ia_ctime = CURRENT_TIME;
333 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
334
335
336
337 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
338 newattrs.ia_mode &= ~S_ISUID;
339 newattrs.ia_valid |= ATTR_MODE;
340 }
341
342
343
344 if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
345 newattrs.ia_mode &= ~S_ISGID;
346 newattrs.ia_valid |= ATTR_MODE;
347 }
348 inode->i_dirt = 1;
349 return notify_change(inode, &newattrs);
350 }
351
352 asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
353 {
354 struct inode * inode;
355 int error;
356 struct iattr newattrs;
357
358 error = lnamei(filename,&inode);
359 if (error)
360 return error;
361 if (IS_RDONLY(inode)) {
362 iput(inode);
363 return -EROFS;
364 }
365 if (user == (uid_t) -1)
366 user = inode->i_uid;
367 if (group == (gid_t) -1)
368 group = inode->i_gid;
369 newattrs.ia_mode = inode->i_mode;
370 newattrs.ia_uid = user;
371 newattrs.ia_gid = group;
372 newattrs.ia_ctime = CURRENT_TIME;
373 newattrs.ia_valid = ATTR_UID | ATTR_GID | ATTR_CTIME;
374
375
376
377 if (user != inode->i_uid && (inode->i_mode & S_ISUID)) {
378 newattrs.ia_mode &= ~S_ISUID;
379 newattrs.ia_valid |= ATTR_MODE;
380 }
381
382
383
384 if (group != inode->i_gid && (inode->i_mode & S_ISGID)) {
385 newattrs.ia_mode &= ~S_ISGID;
386 newattrs.ia_valid |= ATTR_MODE;
387 }
388 inode->i_dirt = 1;
389 error = notify_change(inode, &newattrs);
390 iput(inode);
391 return(error);
392 }
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408 int do_open(const char * filename,int flags,int mode)
409 {
410 struct inode * inode;
411 struct file * f;
412 int flag,error,fd;
413
414 for(fd=0; fd<NR_OPEN && fd<current->rlim[RLIMIT_NOFILE].rlim_cur; fd++)
415 if (!current->files->fd[fd])
416 break;
417 if (fd>=NR_OPEN || fd>=current->rlim[RLIMIT_NOFILE].rlim_cur)
418 return -EMFILE;
419 FD_CLR(fd,¤t->files->close_on_exec);
420 f = get_empty_filp();
421 if (!f)
422 return -ENFILE;
423 current->files->fd[fd] = f;
424 f->f_flags = flag = flags;
425 f->f_mode = (flag+1) & O_ACCMODE;
426 if (f->f_mode)
427 flag++;
428 if (flag & (O_TRUNC | O_CREAT))
429 flag |= 2;
430 error = open_namei(filename,flag,mode,&inode,NULL);
431 if (!error && (f->f_mode & 2)) {
432 error = get_write_access(inode);
433 if (error)
434 iput(inode);
435 }
436 if (error) {
437 current->files->fd[fd]=NULL;
438 f->f_count--;
439 return error;
440 }
441
442 f->f_inode = inode;
443 f->f_pos = 0;
444 f->f_reada = 0;
445 f->f_op = NULL;
446 if (inode->i_op)
447 f->f_op = inode->i_op->default_file_ops;
448 if (f->f_op && f->f_op->open) {
449 error = f->f_op->open(inode,f);
450 if (error) {
451 if (f->f_mode & 2) put_write_access(inode);
452 iput(inode);
453 f->f_count--;
454 current->files->fd[fd]=NULL;
455 return error;
456 }
457 }
458 f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
459 return (fd);
460 }
461
462 asmlinkage int sys_open(const char * filename,int flags,int mode)
463 {
464 char * tmp;
465 int error;
466
467 error = getname(filename, &tmp);
468 if (error)
469 return error;
470 error = do_open(tmp,flags,mode);
471 putname(tmp);
472 return error;
473 }
474
475 asmlinkage int sys_creat(const char * pathname, int mode)
476 {
477 return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
478 }
479
480 int close_fp(struct file *filp)
481 {
482 struct inode *inode;
483
484 if (filp->f_count == 0) {
485 printk("VFS: Close: file count is 0\n");
486 return 0;
487 }
488 inode = filp->f_inode;
489 if (inode)
490 fcntl_remove_locks(current, filp);
491 if (filp->f_count > 1) {
492 filp->f_count--;
493 return 0;
494 }
495 if (filp->f_op && filp->f_op->release)
496 filp->f_op->release(inode,filp);
497 filp->f_count--;
498 filp->f_inode = NULL;
499 if (filp->f_mode & 2) put_write_access(inode);
500 iput(inode);
501 return 0;
502 }
503
504 asmlinkage int sys_close(unsigned int fd)
505 {
506 struct file * filp;
507
508 if (fd >= NR_OPEN)
509 return -EBADF;
510 FD_CLR(fd, ¤t->files->close_on_exec);
511 if (!(filp = current->files->fd[fd]))
512 return -EBADF;
513 current->files->fd[fd] = NULL;
514 return (close_fp (filp));
515 }
516
517
518
519
520
521 asmlinkage int sys_vhangup(void)
522 {
523 if (!suser())
524 return -EPERM;
525
526 if (current->tty)
527 tty_vhangup(current->tty);
528 return 0;
529 }