Xv6 with picoc & Linkage editor
v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
|
00001 // 00002 // File-system system calls. 00003 // Mostly argument checking, since we don't trust 00004 // user code, and calls into file.c and fs.c. 00005 // 00006 00007 #include "types.h" 00008 #include "defs.h" 00009 #include "param.h" 00010 #include "stat.h" 00011 #include "mmu.h" 00012 #include "proc.h" 00013 #include "fs.h" 00014 #include "file.h" 00015 #include "fcntl.h" 00016 00017 // Fetch the nth word-sized system call argument as a file descriptor 00018 // and return both the descriptor and the corresponding struct file. 00019 static int 00020 argfd(int n, int *pfd, struct file **pf) 00021 { 00022 int fd; 00023 struct file *f = 0; 00024 00025 if(argint(n, &fd) < 0) 00026 return -1; 00027 if(fd < 0 || fd >= NOFILE || (f=proc->ofile[fd]) == 0) 00028 return -1; 00029 f=proc->ofile[fd]; 00030 if(pfd) 00031 *pfd = fd; 00032 if(pf) 00033 *pf = f; 00034 return 0; 00035 } 00036 00037 // Allocate a file descriptor for the given file. 00038 // Takes over file reference from caller on success. 00039 static int 00040 fdalloc(struct file *f) 00041 { 00042 int fd; 00043 00044 for(fd = 0; fd < NOFILE; fd++){ 00045 if(proc->ofile[fd] == 0){ 00046 proc->ofile[fd] = f; 00047 return fd; 00048 } 00049 } 00050 return -1; 00051 } 00052 00053 int 00054 sys_dup(void) 00055 { 00056 struct file *f; 00057 int fd; 00058 00059 if(argfd(0, 0, &f) < 0) 00060 return -1; 00061 if((fd=fdalloc(f)) < 0) 00062 return -1; 00063 filedup(f); 00064 return fd; 00065 } 00066 00067 int 00068 sys_read(void) 00069 { 00070 struct file *f; 00071 int n; 00072 char *p; 00073 00074 if( argfd (0,0,&f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) 00075 return -3; 00076 return fileread(f, p, n); 00077 } 00078 00079 int 00080 sys_write(void) 00081 { 00082 struct file *f; 00083 int n; 00084 char *p; 00085 00086 if(argfd(0, 0, &f) < 0 || argint(2, &n) < 0 || argptr(1, &p, n) < 0) 00087 return -1; 00088 return filewrite(f, p, n); 00089 } 00090 00091 int 00092 sys_close(void) 00093 { 00094 int fd; 00095 struct file *f; 00096 00097 if(argfd(0, &fd, &f) < 0) 00098 return -1; 00099 proc->ofile[fd] = 0; 00100 fileclose(f); 00101 return 0; 00102 } 00103 00104 int 00105 sys_fstat(void) 00106 { 00107 struct file *f; 00108 struct stat *st; 00109 00110 if(argfd(0, 0, &f) < 0 || argptr(1, (void*)&st, sizeof(*st)) < 0) 00111 return -1; 00112 return filestat(f, st); 00113 } 00114 00115 // Create the path new as a link to the same inode as old. 00116 int 00117 sys_link(void) 00118 { 00119 char name[DIRSIZ], *new, *old; 00120 struct inode *dp, *ip; 00121 00122 if(argstr(0, &old) < 0 || argstr(1, &new) < 0) 00123 return -1; 00124 if((ip = namei(old)) == 0) 00125 return -1; 00126 00127 begin_trans(); 00128 00129 ilock(ip); 00130 if(ip->type == T_DIR){ 00131 iunlockput(ip); 00132 commit_trans(); 00133 return -1; 00134 } 00135 00136 ip->nlink++; 00137 iupdate(ip); 00138 iunlock(ip); 00139 00140 if((dp = nameiparent(new, name)) == 0) 00141 goto bad; 00142 ilock(dp); 00143 if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){ 00144 iunlockput(dp); 00145 goto bad; 00146 } 00147 iunlockput(dp); 00148 iput(ip); 00149 00150 commit_trans(); 00151 00152 return 0; 00153 00154 bad: 00155 ilock(ip); 00156 ip->nlink--; 00157 iupdate(ip); 00158 iunlockput(ip); 00159 commit_trans(); 00160 return -1; 00161 } 00162 00163 // Is the directory dp empty except for "." and ".." ? 00164 static int 00165 isdirempty(struct inode *dp) 00166 { 00167 int off; 00168 struct dirent de; 00169 00170 for(off=2*sizeof(de); off<dp->size; off+=sizeof(de)){ 00171 if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) 00172 panic("isdirempty: readi"); 00173 if(de.inum != 0) 00174 return 0; 00175 } 00176 return 1; 00177 } 00178 00179 //PAGEBREAK! 00180 int 00181 sys_unlink(void) 00182 { 00183 struct inode *ip, *dp; 00184 struct dirent de; 00185 char name[DIRSIZ], *path; 00186 uint off; 00187 00188 if(argstr(0, &path) < 0) 00189 return -1; 00190 if((dp = nameiparent(path, name)) == 0) 00191 return -1; 00192 00193 begin_trans(); 00194 00195 ilock(dp); 00196 00197 // Cannot unlink "." or "..". 00198 if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0) 00199 goto bad; 00200 00201 if((ip = dirlookup(dp, name, &off)) == 0) 00202 goto bad; 00203 ilock(ip); 00204 00205 if(ip->nlink < 1) 00206 panic("unlink: nlink < 1"); 00207 if(ip->type == T_DIR && !isdirempty(ip)){ 00208 iunlockput(ip); 00209 goto bad; 00210 } 00211 00212 memset(&de, 0, sizeof(de)); 00213 if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de)) 00214 panic("unlink: writei"); 00215 if(ip->type == T_DIR){ 00216 dp->nlink--; 00217 iupdate(dp); 00218 } 00219 iunlockput(dp); 00220 00221 ip->nlink--; 00222 iupdate(ip); 00223 iunlockput(ip); 00224 00225 commit_trans(); 00226 00227 return 0; 00228 00229 bad: 00230 iunlockput(dp); 00231 commit_trans(); 00232 return -1; 00233 } 00234 00235 static struct inode* 00236 create(char *path, short type, short major, short minor) 00237 { 00238 uint off; 00239 struct inode *ip, *dp; 00240 char name[DIRSIZ]; 00241 00242 if((dp = nameiparent(path, name)) == 0) 00243 return 0; 00244 ilock(dp); 00245 00246 if((ip = dirlookup(dp, name, &off)) != 0){ 00247 iunlockput(dp); 00248 ilock(ip); 00249 if(type == T_FILE && ip->type == T_FILE) 00250 return ip; 00251 iunlockput(ip); 00252 return 0; 00253 } 00254 00255 if((ip = ialloc(dp->dev, type)) == 0) 00256 panic("create: ialloc"); 00257 00258 ilock(ip); 00259 ip->major = major; 00260 ip->minor = minor; 00261 ip->nlink = 1; 00262 iupdate(ip); 00263 00264 if(type == T_DIR){ // Create . and .. entries. 00265 dp->nlink++; // for ".." 00266 iupdate(dp); 00267 // No ip->nlink++ for ".": avoid cyclic ref count. 00268 if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0) 00269 panic("create dots"); 00270 } 00271 00272 if(dirlink(dp, name, ip->inum) < 0) 00273 panic("create: dirlink"); 00274 00275 iunlockput(dp); 00276 00277 return ip; 00278 } 00279 00280 int 00281 sys_open(void) 00282 { 00283 char *path; 00284 int fd, omode; 00285 struct file *f; 00286 struct inode *ip; 00287 00288 if(argstr(0, &path) < 0 || argint(1, &omode) < 0) 00289 return -1; 00290 if(omode & O_CREATE){ 00291 begin_trans(); 00292 ip = create(path, T_FILE, 0, 0); 00293 commit_trans(); 00294 if(ip == 0) 00295 return -1; 00296 } else { 00297 if((ip = namei(path)) == 0) 00298 return -1; 00299 ilock(ip); 00300 if(ip->type == T_DIR && omode != O_RDONLY){ 00301 iunlockput(ip); 00302 return -1; 00303 } 00304 } 00305 00306 if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){ 00307 if(f) 00308 fileclose(f); 00309 iunlockput(ip); 00310 return -1; 00311 } 00312 iunlock(ip); 00313 00314 f->type = FD_INODE; 00315 f->ip = ip; 00316 f->off = 0; 00317 f->readable = !(omode & O_WRONLY); 00318 f->writable = (omode & O_WRONLY) || (omode & O_RDWR); 00319 return fd; 00320 } 00321 00322 int 00323 sys_mkdir(void) 00324 { 00325 char *path; 00326 struct inode *ip; 00327 00328 begin_trans(); 00329 if(argstr(0, &path) < 0 || (ip = create(path, T_DIR, 0, 0)) == 0){ 00330 commit_trans(); 00331 return -1; 00332 } 00333 iunlockput(ip); 00334 commit_trans(); 00335 return 0; 00336 } 00337 00338 int 00339 sys_mknod(void) 00340 { 00341 struct inode *ip; 00342 char *path; 00343 int len; 00344 int major, minor; 00345 00346 begin_trans(); 00347 if((len=argstr(0, &path)) < 0 || 00348 argint(1, &major) < 0 || 00349 argint(2, &minor) < 0 || 00350 (ip = create(path, T_DEV, major, minor)) == 0){ 00351 commit_trans(); 00352 return -1; 00353 } 00354 iunlockput(ip); 00355 commit_trans(); 00356 return 0; 00357 } 00358 00359 int 00360 sys_chdir(void) 00361 { 00362 char *path; 00363 struct inode *ip; 00364 00365 if(argstr(0, &path) < 0 || (ip = namei(path)) == 0) 00366 return -1; 00367 ilock(ip); 00368 if(ip->type != T_DIR){ 00369 iunlockput(ip); 00370 return -1; 00371 } 00372 iunlock(ip); 00373 iput(proc->cwd); 00374 proc->cwd = ip; 00375 return 0; 00376 } 00377 00378 int 00379 sys_exec(void) 00380 { 00381 char *path, *argv[MAXARG]; 00382 int i; 00383 uint uargv, uarg; 00384 00385 if(argstr(0, &path) < 0 || argint(1, (int*)&uargv) < 0){ 00386 return -1; 00387 } 00388 memset(argv, 0, sizeof(argv)); 00389 for(i=0;; i++){ 00390 if(i >= NELEM(argv)) 00391 return -1; 00392 if(fetchint(uargv+4*i, (int*)&uarg) < 0) 00393 return -1; 00394 if(uarg == 0){ 00395 argv[i] = 0; 00396 break; 00397 } 00398 if(fetchstr(uarg, &argv[i]) < 0) 00399 return -1; 00400 } 00401 return exec(path, argv); 00402 } 00403 int 00404 sys_lseek(void){ 00405 struct file *f; 00406 int n; 00407 int mode; 00408 if(argfd(0, 0, &f) < 0 || argint(1, &n) < 0 || argint(2, &mode) < 0) 00409 return -1; 00410 return fileseek(f, n, mode); 00411 } 00412 00413 int 00414 sys_pipe(void) 00415 { 00416 int *fd; 00417 struct file *rf, *wf; 00418 int fd0, fd1; 00419 00420 if(argptr(0, (void*)&fd, 2*sizeof(fd[0])) < 0) 00421 return -1; 00422 if(pipealloc(&rf, &wf) < 0) 00423 return -1; 00424 fd0 = -1; 00425 if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){ 00426 if(fd0 >= 0) 00427 proc->ofile[fd0] = 0; 00428 fileclose(rf); 00429 fileclose(wf); 00430 return -1; 00431 } 00432 fd[0] = fd0; 00433 fd[1] = fd1; 00434 return 0; 00435 } 00436