added base src
[xv6-db.git] / sysfile.c
blob0067c632840e5f8e72f2bb718cf941ff6b98f853
1 #include "types.h"
2 #include "defs.h"
3 #include "param.h"
4 #include "stat.h"
5 #include "mmu.h"
6 #include "proc.h"
7 #include "fs.h"
8 #include "file.h"
9 #include "fcntl.h"
11 // Fetch the nth word-sized system call argument as a file descriptor
12 // and return both the descriptor and the corresponding struct file.
13 static int
14 argfd(int n, int *pfd, struct file **pf)
16 int fd;
17 struct file *f;
19 if(argint(n, &fd) < 0)
20 return -1;
21 if(fd < 0 || fd >= NOFILE || (f=proc->ofile[fd]) == 0)
22 return -1;
23 if(pfd)
24 *pfd = fd;
25 if(pf)
26 *pf = f;
27 return 0;
30 // Allocate a file descriptor for the given file.
31 // Takes over file reference from caller on success.
32 static int
33 fdalloc(struct file *f)
35 int fd;
37 for(fd = 0; fd < NOFILE; fd++){
38 if(proc->ofile[fd] == 0){
39 proc->ofile[fd] = f;
40 return fd;
43 return -1;
46 int
47 sys_dup(void)
49 struct file *f;
50 int fd;
52 if(argfd(0, 0, &f) < 0)
53 return -1;
54 if((fd=fdalloc(f)) < 0)
55 return -1;
56 filedup(f);
57 return fd;
60 int
61 sys_read(void)
63 struct file *f;
64 int n;
65 char *p;
67 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
68 return -1;
69 return fileread(f, p, n);
72 int
73 sys_write(void)
75 struct file *f;
76 int n;
77 char *p;
79 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0)
80 return -1;
81 return filewrite(f, p, n);
84 int
85 sys_close(void)
87 int fd;
88 struct file *f;
90 if(argfd(0, &fd, &f) < 0)
91 return -1;
92 proc->ofile[fd] = 0;
93 fileclose(f);
94 return 0;
97 int
98 sys_fstat(void)
100 struct file *f;
101 struct stat *st;
103 if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0)
104 return -1;
105 return filestat(f, st);
108 // Create the path new as a link to the same inode as old.
110 sys_link(void)
112 char name[DIRSIZ], *new, *old;
113 struct inode *dp, *ip;
115 if(argstr(0, &old) < 0 || argstr(1, &new) < 0)
116 return -1;
117 if((ip = namei(old)) == 0)
118 return -1;
119 ilock(ip);
120 if(ip->type == T_DIR){
121 iunlockput(ip);
122 return -1;
124 ip->nlink++;
125 iupdate(ip);
126 iunlock(ip);
128 if((dp = nameiparent(new, name)) == 0)
129 goto bad;
130 ilock(dp);
131 if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){
132 iunlockput(dp);
133 goto bad;
135 iunlockput(dp);
136 iput(ip);
137 return 0;
139 bad:
140 ilock(ip);
141 ip->nlink--;
142 iupdate(ip);
143 iunlockput(ip);
144 return -1;
147 // Is the directory dp empty except for "." and ".." ?
148 static int
149 isdirempty(struct inode *dp)
151 int off;
152 struct dirent de;
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");
157 if(de.inum != 0)
158 return 0;
160 return 1;
164 sys_unlink(void)
166 struct inode *ip, *dp;
167 struct dirent de;
168 char name[DIRSIZ], *path;
169 uint off;
171 if(argstr(0, &path) < 0)
172 return -1;
173 if((dp = nameiparent(path, name)) == 0)
174 return -1;
175 ilock(dp);
177 // Cannot unlink "." or "..".
178 if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0){
179 iunlockput(dp);
180 return -1;
183 if((ip = dirlookup(dp, name, &off)) == 0){
184 iunlockput(dp);
185 return -1;
187 ilock(ip);
189 if(ip->nlink < 1)
190 panic("unlink: nlink < 1");
191 if(ip->type == T_DIR && !isdirempty(ip)){
192 iunlockput(ip);
193 iunlockput(dp);
194 return -1;
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){
201 dp->nlink--;
202 iupdate(dp);
204 iunlockput(dp);
206 ip->nlink--;
207 iupdate(ip);
208 iunlockput(ip);
209 return 0;
212 static struct inode*
213 create(char *path, short type, short major, short minor)
215 uint off;
216 struct inode *ip, *dp;
217 char name[DIRSIZ];
219 if((dp = nameiparent(path, name)) == 0)
220 return 0;
221 ilock(dp);
223 if((ip = dirlookup(dp, name, &off)) != 0){
224 iunlockput(dp);
225 ilock(ip);
226 if(type == T_FILE && ip->type == T_FILE)
227 return ip;
228 iunlockput(ip);
229 return 0;
232 if((ip = ialloc(dp->dev, type)) == 0)
233 panic("create: ialloc");
235 ilock(ip);
236 ip->major = major;
237 ip->minor = minor;
238 ip->nlink = 1;
239 iupdate(ip);
241 if(type == T_DIR){ // Create . and .. entries.
242 dp->nlink++; // for ".."
243 iupdate(dp);
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");
252 iunlockput(dp);
253 return ip;
257 sys_open(void)
259 char *path;
260 int fd, omode;
261 struct file *f;
262 struct inode *ip;
264 if(argstr(0, &path) < 0 || argint(1, &omode) < 0)
265 return -1;
266 if(omode & O_CREATE){
267 if((ip = create(path, T_FILE, 0, 0)) == 0)
268 return -1;
269 } else {
270 if((ip = namei(path)) == 0)
271 return -1;
272 ilock(ip);
273 if(ip->type == T_DIR && omode != O_RDONLY){
274 iunlockput(ip);
275 return -1;
279 if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){
280 if(f)
281 fileclose(f);
282 iunlockput(ip);
283 return -1;
285 iunlock(ip);
287 f->type = FD_INODE;
288 f->ip = ip;
289 f->off = 0;
290 f->readable = !(omode & O_WRONLY);
291 f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
292 return fd;
296 sys_mkdir(void)
298 char *path;
299 struct inode *ip;
301 if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0)
302 return -1;
303 iunlockput(ip);
304 return 0;
308 sys_mknod(void)
310 struct inode *ip;
311 char *path;
312 int len;
313 int major, minor;
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)
319 return -1;
320 iunlockput(ip);
321 return 0;
325 sys_chdir(void)
327 char *path;
328 struct inode *ip;
330 if(argstr(0, &path) < 0 || (ip = namei(path)) == 0)
331 return -1;
332 ilock(ip);
333 if(ip->type != T_DIR){
334 iunlockput(ip);
335 return -1;
337 iunlock(ip);
338 iput(proc->cwd);
339 proc->cwd = ip;
340 return 0;
344 sys_exec(void)
346 char *path, *argv[MAXARG];
347 int i;
348 uint uargv, uarg;
350 if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){
351 return -1;
353 memset(argv, 0, sizeof(argv));
354 for(i=0;; i++){
355 if(i >= NELEM(argv))
356 return -1;
357 if(fetchint(proc, uargv+4*i, (int*)&uarg) < 0)
358 return -1;
359 if(uarg == 0){
360 argv[i] = 0;
361 break;
363 if(fetchstr(proc, uarg, &argv[i]) < 0)
364 return -1;
366 return exec(path, argv);
370 sys_pipe(void)
372 int *fd;
373 struct file *rf, *wf;
374 int fd0, fd1;
376 if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0)
377 return -1;
378 if(pipealloc(&rf, &wf) < 0)
379 return -1;
380 fd0 = -1;
381 if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
382 if(fd0 >= 0)
383 proc->ofile[fd0] = 0;
384 fileclose(rf);
385 fileclose(wf);
386 return -1;
388 fd[0] = fd0;
389 fd[1] = fd1;
390 return 0;