diff --git a/fs.c b/fs.c index a83e937..6c552e6 100644 --- a/fs.c +++ b/fs.c @@ -499,7 +499,10 @@ namei(char *path, int mode, uint *ret_off, char **ret_last, struct inode **ret_i for(i = 0; i < DIRSIZ && cp[i] != '/' && cp[i]; i++) if(cp[i] != ep->name[i]) break; - if((cp[i] == '\0' || cp[i] == '/') && (i >= DIRSIZ || ep->name[i] == '\0')){ + if((cp[i] == '\0' || cp[i] == '/' || i >= DIRSIZ) && + (i >= DIRSIZ || ep->name[i] == '\0')){ + while(cp[i] != '\0' && cp[i] != '/') + i++; off += (uchar*)ep - bp->data; ninum = ep->inum; brelse(bp); diff --git a/fstests.c b/fstests.c index d6356ac..ac9478e 100644 --- a/fstests.c +++ b/fstests.c @@ -412,8 +412,9 @@ bigdir() void subdir() { - int fd; + int fd, cc; + unlink("ff"); if(mkdir("dd") != 0){ puts("subdir mkdir dd failed\n"); exit(); @@ -440,6 +441,18 @@ subdir() write(fd, "FF", 2); close(fd); + fd = open("dd/dd/../ff", 0); + if(fd < 0){ + puts("open dd/dd/../ff failed\n"); + exit(); + } + cc = read(fd, buf, sizeof(buf)); + if(cc != 2 || buf[0] != 'f'){ + puts("dd/dd/../ff wrong content\n"); + exit(); + } + close(fd); + if(link("dd/dd/ff", "dd/dd/ffff") != 0){ puts("link dd/dd/ff dd/dd/ffff failed\n"); exit(); @@ -487,6 +500,18 @@ subdir() puts("create dd/xx/ff succeeded!\n"); exit(); } + if(open("dd", O_CREATE) >= 0){ + puts("create dd succeeded!\n"); + exit(); + } + if(open("dd", O_RDWR) >= 0){ + puts("open dd rdwr succeeded!\n"); + exit(); + } + if(open("dd", O_WRONLY) >= 0){ + puts("open dd wronly succeeded!\n"); + exit(); + } if(link("dd/ff/ff", "dd/dd/xx") == 0){ puts("link dd/ff/ff dd/dd/xx succeeded!\n"); exit(); @@ -597,11 +622,50 @@ bigfile() puts("bigfile ok\n"); } +void +fourteen() +{ + int fd; + + if(mkdir("12345678901234") != 0){ + puts("mkdir 12345678901234 failed\n"); + exit(); + } + if(mkdir("12345678901234/123456789012345") != 0){ + puts("mkdir 12345678901234/123456789012345 failed\n"); + exit(); + } + fd = open("123456789012345/123456789012345/123456789012345", O_CREATE); + if(fd < 0){ + puts("create 123456789012345/123456789012345/123456789012345 failed\n"); + exit(); + } + close(fd); + fd = open("12345678901234/12345678901234/12345678901234", 0); + if(fd < 0){ + puts("open 12345678901234/12345678901234/12345678901234 failed\n"); + exit(); + } + close(fd); + + if(mkdir("12345678901234/12345678901234") == 0){ + puts("mkdir 12345678901234/12345678901234 succeeded!\n"); + exit(); + } + if(mkdir("123456789012345/12345678901234") == 0){ + puts("mkdir 12345678901234/123456789012345 succeeded!\n"); + exit(); + } + + puts("fourteen ok\n"); +} + int main(int argc, char *argv[]) { puts("fstests starting\n"); + fourteen(); bigfile(); subdir(); // bigdir(); // slow diff --git a/syscall.c b/syscall.c index 9e256a8..b0933db 100644 --- a/syscall.c +++ b/syscall.c @@ -240,12 +240,19 @@ sys_open(void) return -1; } else if(ip == 0){ return -1; + } else if(ip->type == T_DIR){ + iput(ip); + return -1; } } else { ip = namei(cp->mem + arg0, NAMEI_LOOKUP, 0, 0, 0); if(ip == 0) return -1; } + if(ip->type == T_DIR && ((arg1 & O_RDWR) || (arg1 & O_WRONLY))){ + iput(ip); + return -1; + } if((fd = fd_alloc()) == 0){ iput(ip); @@ -305,10 +312,11 @@ sys_mkdir(void) { struct proc *cp = curproc[cpu()]; struct inode *nip; - struct inode *pip; + struct inode *dp; uint arg0; int l; struct dirent de; + char *last; if(fetcharg(0, &arg0) < 0) return -1; @@ -316,26 +324,32 @@ sys_mkdir(void) if((l = checkstring(arg0)) < 0) return -1; - if(l >= DIRSIZ) + dp = namei(cp->mem + arg0, NAMEI_CREATE, 0, &last, 0); + if(dp == 0) return -1; - nip = mknod (cp->mem + arg0, T_DIR, 0, 0); - if(nip == 0) + nip = mknod1(dp, last, T_DIR, 0, 0); + if(nip == 0){ + iput(dp); return -1; + } + + dp->nlink += 1; + iupdate(dp); memset (de.name, '\0', DIRSIZ); de.name[0] = '.'; de.inum = nip->inum; writei (nip, (char *) &de, 0, sizeof(de)); - pip = namei(".", NAMEI_LOOKUP, 0, 0, 0); - de.inum = pip->inum; + de.inum = dp->inum; de.name[1] = '.'; - iput(pip); writei (nip, (char *) &de, sizeof(de), sizeof(de)); + iput(dp); iput(nip); - return (nip == 0) ? -1 : 0; + + return 0; }