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
sysfile.c
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 
 All Data Structures