11 // Fetch the nth word-sized system call argument as a file descriptor
12 // and return both the descriptor and the corresponding struct file.
14 argfd(int n
, int *pfd
, struct file
**pf
)
19 if(argint(n
, &fd
) < 0)
21 if(fd
< 0 || fd
>= NOFILE
|| (f
=proc
->ofile
[fd
]) == 0)
30 // Allocate a file descriptor for the given file.
31 // Takes over file reference from caller on success.
33 fdalloc(struct file
*f
)
37 for(fd
= 0; fd
< NOFILE
; fd
++){
38 if(proc
->ofile
[fd
] == 0){
52 if(argfd(0, 0, &f
) < 0)
54 if((fd
=fdalloc(f
)) < 0)
67 if(argfd(0, 0, &f
) < 0 || argint(2, &n
) < 0 || argptr(1, &p
, n
) < 0)
69 return fileread(f
, p
, n
);
79 if(argfd(0, 0, &f
) < 0 || argint(2, &n
) < 0 || argptr(1, &p
, n
) < 0)
81 return filewrite(f
, p
, n
);
90 if(argfd(0, &fd
, &f
) < 0)
103 if(argfd(0, 0, &f
) < 0 || argptr(1, (void*)&st
, sizeof(*st
)) < 0)
105 return filestat(f
, st
);
108 // Create the path new as a link to the same inode as old.
112 char name
[DIRSIZ
], *new, *old
;
113 struct inode
*dp
, *ip
;
115 if(argstr(0, &old
) < 0 || argstr(1, &new) < 0)
117 if((ip
= namei(old
)) == 0)
120 if(ip
->type
== T_DIR
){
128 if((dp
= nameiparent(new, name
)) == 0)
131 if(dp
->dev
!= ip
->dev
|| dirlink(dp
, name
, ip
->inum
) < 0){
147 // Is the directory dp empty except for "." and ".." ?
149 isdirempty(struct inode
*dp
)
154 for(off
=2*sizeof(de
); off
<dp
->size
; off
+=sizeof(de
)){
155 if(readi(dp
, (char*)&de
, off
, sizeof(de
)) != sizeof(de
))
156 panic("isdirempty: readi");
166 struct inode
*ip
, *dp
;
168 char name
[DIRSIZ
], *path
;
171 if(argstr(0, &path
) < 0)
173 if((dp
= nameiparent(path
, name
)) == 0)
177 // Cannot unlink "." or "..".
178 if(namecmp(name
, ".") == 0 || namecmp(name
, "..") == 0){
183 if((ip
= dirlookup(dp
, name
, &off
)) == 0){
190 panic("unlink: nlink < 1");
191 if(ip
->type
== T_DIR
&& !isdirempty(ip
)){
197 memset(&de
, 0, sizeof(de
));
198 if(writei(dp
, (char*)&de
, off
, sizeof(de
)) != sizeof(de
))
199 panic("unlink: writei");
200 if(ip
->type
== T_DIR
){
213 create(char *path
, short type
, short major
, short minor
)
216 struct inode
*ip
, *dp
;
219 if((dp
= nameiparent(path
, name
)) == 0)
223 if((ip
= dirlookup(dp
, name
, &off
)) != 0){
226 if(type
== T_FILE
&& ip
->type
== T_FILE
)
232 if((ip
= ialloc(dp
->dev
, type
)) == 0)
233 panic("create: ialloc");
241 if(type
== T_DIR
){ // Create . and .. entries.
242 dp
->nlink
++; // for ".."
244 // No ip->nlink++ for ".": avoid cyclic ref count.
245 if(dirlink(ip
, ".", ip
->inum
) < 0 || dirlink(ip
, "..", dp
->inum
) < 0)
246 panic("create dots");
249 if(dirlink(dp
, name
, ip
->inum
) < 0)
250 panic("create: dirlink");
264 if(argstr(0, &path
) < 0 || argint(1, &omode
) < 0)
266 if(omode
& O_CREATE
){
267 if((ip
= create(path
, T_FILE
, 0, 0)) == 0)
270 if((ip
= namei(path
)) == 0)
273 if(ip
->type
== T_DIR
&& omode
!= O_RDONLY
){
279 if((f
= filealloc()) == 0 || (fd
= fdalloc(f
)) < 0){
290 f
->readable
= !(omode
& O_WRONLY
);
291 f
->writable
= (omode
& O_WRONLY
) || (omode
& O_RDWR
);
301 if(argstr(0, &path
) < 0 || (ip
= create(path
, T_DIR
, 0, 0)) == 0)
315 if((len
=argstr(0, &path
)) < 0 ||
316 argint(1, &major
) < 0 ||
317 argint(2, &minor
) < 0 ||
318 (ip
= create(path
, T_DEV
, major
, minor
)) == 0)
330 if(argstr(0, &path
) < 0 || (ip
= namei(path
)) == 0)
333 if(ip
->type
!= T_DIR
){
346 char *path
, *argv
[MAXARG
];
350 if(argstr(0, &path
) < 0 || argint(1, (int*)&uargv
) < 0){
353 memset(argv
, 0, sizeof(argv
));
357 if(fetchint(proc
, uargv
+4*i
, (int*)&uarg
) < 0)
363 if(fetchstr(proc
, uarg
, &argv
[i
]) < 0)
366 return exec(path
, argv
);
373 struct file
*rf
, *wf
;
376 if(argptr(0, (void*)&fd
, 2*sizeof(fd
[0])) < 0)
378 if(pipealloc(&rf
, &wf
) < 0)
381 if((fd0
= fdalloc(rf
)) < 0 || (fd1
= fdalloc(wf
)) < 0){
383 proc
->ofile
[fd0
] = 0;