diff options
| author | rtm <rtm> | 2006-08-13 02:12:44 +0000 | 
|---|---|---|
| committer | rtm <rtm> | 2006-08-13 02:12:44 +0000 | 
| commit | 9e5970d596d7b1634200d50e96130886f593cede (patch) | |
| tree | 994e11ccb4a3a33c1963a8f1fb3f7464d3d9e363 | |
| parent | 05e975511bcf7f33955208319655dbfc687a7b0c (diff) | |
| download | xv6-labs-9e5970d596d7b1634200d50e96130886f593cede.tar.gz xv6-labs-9e5970d596d7b1634200d50e96130886f593cede.tar.bz2 xv6-labs-9e5970d596d7b1634200d50e96130886f593cede.zip | |
link()
| -rw-r--r-- | Notes | 4 | ||||
| -rw-r--r-- | defs.h | 1 | ||||
| -rw-r--r-- | fs.c | 89 | ||||
| -rw-r--r-- | ide.c | 2 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rw-r--r-- | proc.c | 3 | ||||
| -rw-r--r-- | syscall.c | 19 | ||||
| -rw-r--r-- | syscall.h | 1 | ||||
| -rw-r--r-- | user.h | 1 | ||||
| -rw-r--r-- | usertests.c | 61 | ||||
| -rw-r--r-- | usys.S | 1 | 
11 files changed, 149 insertions, 39 deletions
| @@ -355,8 +355,6 @@ HMM maybe the variables at the end of struct cpu are being overwritten  OH! recursive interrupts will use up any amount of cpu[].stack!    underflow and wrecks *previous* cpu's struct -better buffer cache replacement -read/write of open file that's been unlinked  disk scheduling  mkdir  more than one directory content block @@ -365,3 +363,5 @@ sh redirection  indirect blocks  two bugs in unlink: don't just return if nlink > 0,    and search for name, not inum +is there a create/create race for same file name? +  resulting in two entries w/ same name in directory? @@ -123,3 +123,4 @@ int writei(struct inode *ip, char *addr, uint off, uint n);  struct inode *mknod(char *, short, short, short);  int unlink(char *cp);  void iupdate (struct inode *ip); +int link(char *file1, char *file2); @@ -439,14 +439,41 @@ namei(char *path, uint *ret_pinum)    }  } +void +wdir(struct inode *dp, char *name, uint ino) +{ +  uint off; +  struct buf *bp = 0; +  struct dirent *ep = 0; +  int i; + +  for(off = 0; off < dp->size; off += BSIZE) { +    bp = bread(dp->dev, bmap(dp, off / BSIZE)); +    for(ep = (struct dirent *) bp->data; +	ep < (struct dirent *) (bp->data + BSIZE); +	ep++){ +      if(ep->inum == 0) +	goto found; +    } +    brelse(bp); +  } + +  panic("mknod: XXXX no dir entry free\n"); + + found: +  ep->inum = ino; +  for(i = 0; i < DIRSIZ && name[i]; i++) +    ep->name[i] = name[i]; +  for( ; i < DIRSIZ; i++) +    ep->name[i] = '\0'; +  bwrite (bp, bmap(dp, off/BSIZE));   // write directory block +  brelse(bp); +} +  struct inode *  mknod(char *cp, short type, short major, short minor)  {    struct inode *ip, *dp; -  struct dirent *ep = 0; -  int off; -  int i; -  struct buf *bp = 0;    uint pinum = 0;    cprintf("mknod: %s %d %d %d\n", cp, type, major, minor); @@ -469,27 +496,7 @@ mknod(char *cp, short type, short major, short minor)    iupdate (ip);  // write new inode to disk -  for(off = 0; off < dp->size; off += BSIZE) { -    bp = bread(dp->dev, bmap(dp, off / BSIZE)); -    for(ep = (struct dirent *) bp->data; -	ep < (struct dirent *) (bp->data + BSIZE); -	ep++){ -      if(ep->inum == 0) { -	goto found; -      } -    } -    brelse(bp); -  } -  panic("mknod: XXXX no dir entry free\n"); - - found: -  ep->inum = ip->inum; -  for(i = 0; i < DIRSIZ && cp[i]; i++) -    ep->name[i] = cp[i]; -  for( ; i < DIRSIZ; i++) -    ep->name[i] = '\0'; -  bwrite (bp, bmap(dp, off/BSIZE));   // write directory block -  brelse(bp); +  wdir(dp, cp, ip->inum);    iput(dp); @@ -541,3 +548,35 @@ unlink(char *cp)    iput(ip);    return 0;  } + +int +link(char *name1, char *name2) +{ +  struct inode *ip, *dp, *xip; +  uint pinum = 0; + +  cprintf("link(%s, %s)\n", name1, name2); + +  if ((xip = namei(name2, &pinum)) != 0) { +    cprintf("  failed %s exists\n", name2); +    iput(xip); +    return -1; +  } + +  if ((ip = namei(name1, &pinum)) == 0){ +    cprintf("  failed %s does not exist\n", name1); +    return -1; +  } +   +  ip->nlink += 1; +  iupdate (ip); + +  dp = iget(rootdev, pinum); +  wdir(dp, name2, ip->inum); +  iput(dp); +  iput(ip); + +  cprintf("  succeeded\n"); + +  return 0; +} @@ -52,14 +52,12 @@ ide_init(void)    }    ioapic_enable (IRQ_IDE, 1);    ide_wait_ready(0); -  cprintf ("cpu%d: ide_init:done\n", cpu());  }  void  ide_intr(void)  {    acquire(&ide_lock); -  //  cprintf("cpu%d: ide_intr\n", cpu());    wakeup(&request[tail]);    release(&ide_lock);  } @@ -87,8 +87,6 @@ main0(void)    lapic_enableintr();    // Enable interrupts on this processor. -  cprintf("cpu%d: nlock %d before -- and sti\n", -          cpu(), cpus[0].nlock);    cpus[cpu()].nlock--;    sti(); @@ -98,7 +96,6 @@ main0(void)    //load_icode(p, _binary_userfs_start, (uint) _binary_userfs_size);    load_icode(p, _binary_init_start, (uint) _binary_init_size);    p->state = RUNNABLE; -  cprintf("loaded init\n");    scheduler();  } @@ -123,7 +120,6 @@ mpmain(void)    cpus[cpu()].booted = 1;    // Enable interrupts on this processor. -  cprintf("cpu%d: initial nlock %d\n", cpu(), cpus[cpu()].nlock);    cpus[cpu()].nlock--;    sti(); @@ -139,7 +135,6 @@ load_icode(struct proc *p, uchar *binary, uint size)    // Check magic number on binary    elf = (struct elfhdr*) binary; -  cprintf("elf %x magic %x\n", elf, elf->magic);    if (elf->magic != ELF_MAGIC)      panic("load_icode: not an ELF binary"); @@ -151,7 +146,6 @@ load_icode(struct proc *p, uchar *binary, uint size)    for (i = 0; i < elf->phnum; i++, ph++) {      if (ph->type != ELF_PROG_LOAD)        continue; -    cprintf("va %x memsz %d\n", ph->va, ph->memsz);      if (ph->va + ph->memsz < ph->va)        panic("load_icode: overflow in elf header segment");      if (ph->va + ph->memsz >= p->sz) @@ -140,9 +140,6 @@ scheduler(void)    struct proc *p;    int i; -  cprintf("cpu%d: start scheduler jmpbuf %p\n", -          cpu(), &cpus[cpu()].jmpbuf); -    if(cpus[cpu()].nlock != 0){      cprintf("la %x lr %x\n", cpus[cpu()].lastacquire, cpus[cpu()].lastrelease   );      panic("holding locks at first entry to scheduler"); @@ -303,7 +303,6 @@ sys_unlink(void)    return r;  } -  int  sys_fstat(void)  { @@ -326,6 +325,21 @@ sys_fstat(void)  }  int +sys_link(void) +{ +  struct proc *cp = curproc[cpu()]; +  uint name1, name2; +  int r; +   +  if(fetcharg(0, &name1) < 0 || checkstring(name1) < 0) +    return -1; +  if(fetcharg(1, &name2) < 0 || checkstring(name2) < 0) +    return -1; +  r = link(cp->mem + name1, cp->mem + name2); +  return r; +} + +int  sys_exec(void)  {    struct proc *cp = curproc[cpu()]; @@ -543,6 +557,9 @@ syscall(void)    case SYS_fstat:      ret = sys_fstat();      break; +  case SYS_link: +    ret = sys_link(); +    break;    default:      cprintf("unknown sys call %d\n", num);      // XXX fault @@ -12,4 +12,5 @@  #define SYS_mknod 15  #define SYS_unlink 16  #define SYS_fstat 17 +#define SYS_link 18 @@ -16,6 +16,7 @@ int mknod (char*,short,short,short);  int unlink (char*);  struct stat;  int fstat (int fd, struct stat *stat); +int link(char *, char *);  int puts(char*);  char* strcpy(char*, char*); diff --git a/usertests.c b/usertests.c index 3cb4a37..2d6b065 100644 --- a/usertests.c +++ b/usertests.c @@ -344,11 +344,72 @@ unlinkread()    puts("unlinkread ok\n");  } +void +linktest() +{ +  int fd; + +  unlink("lf1"); +  unlink("lf2"); + +  fd = open("lf1", O_CREATE|O_RDWR); +  if(fd < 0){ +    puts("create lf1 failed\n"); +    exit(); +  } +  if(write(fd, "hello", 5) != 5){ +    puts("write lf1 failed\n"); +    exit(); +  } +  close(fd); + +  if(link("lf1", "lf2") < 0){ +    puts("link lf1 lf2 failed\n"); +    exit(); +  } +  unlink("lf1"); + +  if(open("lf1", 0) >= 0){ +    puts("unlinked lf1 but it is still there!\n"); +    exit(); +  } + +  fd = open("lf2", 0); +  if(fd < 0){ +    puts("open lf2 failed\n"); +    exit(); +  } +  if(read(fd, buf, sizeof(buf)) != 5){ +    puts("read lf2 failed\n"); +    exit(); +  } +  close(fd); +     +  if(link("lf2", "lf2") >= 0){ +    puts("link lf2 lf2 succeeded! oops\n"); +    exit(); +  } + +  unlink("lf2"); +  if(link("lf2", "lf1") >= 0){ +    puts("link non-existant succeeded! oops\n"); +    exit(); +  } + +  if(link(".", "lf1") >= 0){ +    puts("link . lf1 succeeded! oops\n"); +    exit(); +  } + +  puts("linktest ok\n"); +} +  int  main(int argc, char *argv[])  {    puts("usertests starting\n"); +  linktest();    unlinkread();    createdelete();    twofiles(); @@ -22,3 +22,4 @@ STUB(open)  STUB(mknod)  STUB(unlink)  STUB(fstat) +STUB(link) | 
