link()
This commit is contained in:
		
							parent
							
								
									05e975511b
								
							
						
					
					
						commit
						9e5970d596
					
				
					 11 changed files with 149 additions and 39 deletions
				
			
		
							
								
								
									
										4
									
								
								Notes
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Notes
									
										
									
									
									
								
							|  | @ -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? | ||||
|  |  | |||
							
								
								
									
										1
									
								
								defs.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								defs.h
									
										
									
									
									
								
							|  | @ -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); | ||||
|  |  | |||
							
								
								
									
										89
									
								
								fs.c
									
										
									
									
									
								
							
							
						
						
									
										89
									
								
								fs.c
									
										
									
									
									
								
							|  | @ -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; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										2
									
								
								ide.c
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								ide.c
									
										
									
									
									
								
							|  | @ -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); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										6
									
								
								main.c
									
										
									
									
									
								
							
							
						
						
									
										6
									
								
								main.c
									
										
									
									
									
								
							|  | @ -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) | ||||
|  |  | |||
							
								
								
									
										3
									
								
								proc.c
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								proc.c
									
										
									
									
									
								
							|  | @ -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"); | ||||
|  |  | |||
							
								
								
									
										19
									
								
								syscall.c
									
										
									
									
									
								
							
							
						
						
									
										19
									
								
								syscall.c
									
										
									
									
									
								
							|  | @ -303,7 +303,6 @@ sys_unlink(void) | |||
|   return r; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| int | ||||
| sys_fstat(void) | ||||
| { | ||||
|  | @ -325,6 +324,21 @@ sys_fstat(void) | |||
|   return r; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								user.h
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								user.h
									
										
									
									
									
								
							|  | @ -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*); | ||||
|  |  | |||
							
								
								
									
										61
									
								
								usertests.c
									
										
									
									
									
								
							
							
						
						
									
										61
									
								
								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(); | ||||
|  |  | |||
							
								
								
									
										1
									
								
								usys.S
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								usys.S
									
										
									
									
									
								
							|  | @ -22,3 +22,4 @@ STUB(open) | |||
| STUB(mknod) | ||||
| STUB(unlink) | ||||
| STUB(fstat) | ||||
| STUB(link) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 rtm
						rtm