diff --git a/Makefile b/Makefile index 212952f5873cb361f5e53e8f3db4fade58aa4c47..ec2531ad5f3950694c66181bd678ec2729df86c8 100644 --- a/Makefile +++ b/Makefile @@ -202,7 +202,8 @@ UPROGS=\ $U/_wc\ $U/_test\ $U/_usertests\ - $U/_strace + $U/_strace\ + $U/_mv # $U/_forktest\ # $U/_ln\ @@ -220,7 +221,7 @@ dst=/mnt fs: $(UPROGS) @if [ ! -f "fs.img" ]; then \ echo "making fs image..."; \ - dd if=/dev/zero of=fs.img bs=512k count=1024; \ + dd if=/dev/zero of=fs.img bs=512k count=512; \ mkfs.vfat -F 32 fs.img; fi @sudo mount fs.img $(dst) @if [ ! -d "$(dst)/bin" ]; then sudo mkdir $(dst)/bin; fi diff --git a/kernel/fat32.c b/kernel/fat32.c index 80a6fe792b30c10a2941a74b32e0fc1d6e4ea955..a75a72f85ce074089bb8818860732a0c76302c59 100644 --- a/kernel/fat32.c +++ b/kernel/fat32.c @@ -336,7 +336,8 @@ int eread(struct dirent *entry, int user_dst, uint64 dst, uint off, uint n) // Caller must hold entry->lock. int ewrite(struct dirent *entry, int user_src, uint64 src, uint off, uint n) { - if (off > entry->file_size || off + n < off || (entry->attribute & ATTR_READ_ONLY)) { + if (off > entry->file_size || off + n < off || (uint64)off + n > 0xffffffff + || (entry->attribute & ATTR_READ_ONLY)) { return -1; } if (entry->first_clus == 0) { // so file_size if 0 too, which requests off == 0 @@ -377,9 +378,11 @@ static struct dirent *eget(struct dirent *parent, char *name) for (ep = root.next; ep != &root; ep = ep->next) { // LRU algo if (ep->valid == 1 && ep->parent == parent && strncmp(ep->filename, name, FAT32_MAX_FILENAME) == 0) { - ep->ref++; + if (ep->ref++ == 0) { + ep->parent->ref++; + } release(&ecache.lock); - edup(ep->parent); + // edup(ep->parent); return ep; } } @@ -390,6 +393,7 @@ static struct dirent *eget(struct dirent *parent, char *name) ep->dev = parent->dev; ep->off = 0; ep->valid = 0; + ep->dirty = 0; release(&ecache.lock); return ep; } @@ -399,9 +403,9 @@ static struct dirent *eget(struct dirent *parent, char *name) } // trim ' ' in the head and tail, '.' in head, and test legality -static char *formatname(char *name) +char *formatname(char *name) { - static char illegal[] = { '\"', '*', '/', ':', '<', '>', '?', '\\', '|' }; + static char illegal[] = { '\"', '*', '/', ':', '<', '>', '?', '\\', '|', 0 }; char *p; while (*name == ' ' || *name == '.') { name++; } for (p = name; *p; p++) { @@ -421,7 +425,7 @@ static char *formatname(char *name) static void generate_shortname(char *shortname, char *name) { - static char illegal[] = { '+', ',', ';', '=', '[', ']' }; // these are legal in l-n-e but not s-n-e + static char illegal[] = { '+', ',', ';', '=', '[', ']', 0 }; // these are legal in l-n-e but not s-n-e int i = 0; char c, *p = name; for (int j = strlen(name) - 1; j >= 0; j--) { @@ -470,49 +474,80 @@ uint8 cal_checksum(uchar* shortname) } /** - * Generate an entry in the raw type and write to the disk. - * @param data for s-n-e it's the first cluster, for l-n-e it's the ordinal. - * @param checksum only for l-n-e, the checksum. + * Generate an on disk format entry and write to the disk. Caller must hold dp->lock + * @param dp the directory + * @param ep entry to write on disk + * @param off offset int the dp, should be calculated via dirlookup before calling this */ -static void make_entry(struct dirent *dp, uint off, char *name, uint8 attr, uint32 data, uint8 checksum) +void emake(struct dirent *dp, struct dirent *ep, uint off) { + if (!(dp->attribute & ATTR_DIRECTORY)) + panic("emake: not dir"); + if (off % sizeof(union dentry)) + panic("emake: not aligned"); + union dentry de; memset(&de, 0, sizeof(de)); - if ((de.sne.attr = attr) == ATTR_LONG_NAME) { - de.lne.order = data; - de.lne.checksum = checksum; - name += ((data & ~LAST_LONG_ENTRY) - 1) * CHAR_LONG_NAME; - uint8 *w = (uint8 *)de.lne.name1; - int end = 0; - for (int i = 1; i <= CHAR_LONG_NAME; i++) { - if (end) { - *w++ = 0xff; // on k210, unaligned reading is illegal - *w++ = 0xff; - } else { - if ((*w++ = *name++) == 0) { - end = 1; - } - *w++ = 0; + if (off <= 32) { + if (off == 0) { + strncpy(de.sne.name, ". ", sizeof(de.sne.name)); + } else { + strncpy(de.sne.name, ".. ", sizeof(de.sne.name)); + } + de.sne.attr = ATTR_DIRECTORY; + de.sne.fst_clus_hi = (uint16)(ep->first_clus >> 16); // first clus high 16 bits + de.sne.fst_clus_lo = (uint16)(ep->first_clus & 0xffff); // low 16 bits + de.sne.file_size = 0; // filesize is updated in eupdate() + off = reloc_clus(dp, off, 1); + rw_clus(dp->cur_clus, 1, 0, (uint64)&de, off, sizeof(de)); + } else { + int entcnt = (strlen(ep->filename) + CHAR_LONG_NAME - 1) / CHAR_LONG_NAME; // count of l-n-entries, rounds up + char shortname[CHAR_SHORT_NAME + 1]; + memset(shortname, 0, sizeof(shortname)); + generate_shortname(shortname, ep->filename); + de.lne.checksum = cal_checksum((uchar *)shortname); + de.lne.attr = ATTR_LONG_NAME; + for (int i = entcnt; i > 0; i--) { + if ((de.lne.order = i) == entcnt) { + de.lne.order |= LAST_LONG_ENTRY; } - switch (i) { - case 5: w = (uint8 *)de.lne.name2; break; - case 11: w = (uint8 *)de.lne.name3; break; + char *p = ep->filename + (i - 1) * CHAR_LONG_NAME; + uint8 *w = (uint8 *)de.lne.name1; + int end = 0; + for (int j = 1; j <= CHAR_LONG_NAME; j++) { + if (end) { + *w++ = 0xff; // on k210, unaligned reading is illegal + *w++ = 0xff; + } else { + if ((*w++ = *p++) == 0) { + end = 1; + } + *w++ = 0; + } + switch (j) { + case 5: w = (uint8 *)de.lne.name2; break; + case 11: w = (uint8 *)de.lne.name3; break; + } } + uint off2 = reloc_clus(dp, off, 1); + rw_clus(dp->cur_clus, 1, 0, (uint64)&de, off2, sizeof(de)); + off += sizeof(de); } - } else { - strncpy(de.sne.name, name, sizeof(de.sne.name)); - de.sne.fst_clus_hi = (uint16)(data >> 16); // first clus high 16 bits - de.sne.fst_clus_lo = (uint16)(data & 0xff); // low 16 bits - de.sne.file_size = 0; // filesize is updated in eupdate() + memset(&de, 0, sizeof(de)); + strncpy(de.sne.name, shortname, sizeof(de.sne.name)); + de.sne.attr = ep->attribute; + de.sne.fst_clus_hi = (uint16)(ep->first_clus >> 16); // first clus high 16 bits + de.sne.fst_clus_lo = (uint16)(ep->first_clus & 0xffff); // low 16 bits + de.sne.file_size = ep->file_size; // filesize is updated in eupdate() + off = reloc_clus(dp, off, 1); + rw_clus(dp->cur_clus, 1, 0, (uint64)&de, off, sizeof(de)); } - off = reloc_clus(dp, off, 1); - rw_clus(dp->cur_clus, 1, 0, (uint64)&de, off, sizeof(de)); } /** * Allocate an entry on disk. Caller must hold dp->lock. */ -struct dirent *ealloc(struct dirent *dp, char *name, int dir) +struct dirent *ealloc(struct dirent *dp, char *name, int attr) { if (!(dp->attribute & ATTR_DIRECTORY)) { panic("ealloc not dir"); @@ -527,7 +562,7 @@ struct dirent *ealloc(struct dirent *dp, char *name, int dir) } ep = eget(dp, name); elock(ep); - ep->attribute = 0; + ep->attribute = attr; ep->file_size = 0; ep->first_clus = 0; ep->parent = edup(dp); @@ -537,29 +572,15 @@ struct dirent *ealloc(struct dirent *dp, char *name, int dir) ep->dirty = 0; strncpy(ep->filename, name, FAT32_MAX_FILENAME); ep->filename[FAT32_MAX_FILENAME] = '\0'; - - if (dir) { // generate "." and ".." for ep + if (attr == ATTR_DIRECTORY) { // generate "." and ".." for ep ep->attribute |= ATTR_DIRECTORY; ep->cur_clus = ep->first_clus = alloc_clus(dp->dev); - make_entry(ep, 0, ". ", ATTR_DIRECTORY, ep->first_clus, 0); - make_entry(ep, 32, ".. ", ATTR_DIRECTORY, dp->first_clus, 0); + emake(ep, ep, 0); + emake(ep, dp, 32); } else { ep->attribute |= ATTR_ARCHIVE; } - int entcnt = (strlen(name) + CHAR_LONG_NAME - 1) / CHAR_LONG_NAME; // count of l-n-entries, rounds up - char shortname[CHAR_SHORT_NAME + 1]; - memset(shortname, 0, sizeof(shortname)); - generate_shortname(shortname, name); - uint8 checksum = cal_checksum((uchar *)shortname); - for (int i = entcnt; i > 0; i--) { - int longnum = i; - if (i == entcnt) { - longnum |= LAST_LONG_ENTRY; - } - make_entry(dp, off, ep->filename, ATTR_LONG_NAME, longnum, checksum); - off += 32; - } - make_entry(dp, off, shortname, ep->attribute, ep->first_clus, 0); + emake(dp, ep, off); ep->valid = 1; eunlock(ep); return ep; @@ -576,11 +597,11 @@ struct dirent *edup(struct dirent *entry) } // Only update filesize and first cluster in this case. +// caller must hold entry->parent->lock void eupdate(struct dirent *entry) { if (!entry->dirty || entry->valid != 1) { return; } uint entcnt = 0; - elock(entry->parent); uint32 off = reloc_clus(entry->parent, entry->off, 0); rw_clus(entry->parent->cur_clus, 0, 0, (uint64) &entcnt, off, 1); entcnt &= ~LAST_LONG_ENTRY; @@ -588,19 +609,19 @@ void eupdate(struct dirent *entry) union dentry de; rw_clus(entry->parent->cur_clus, 0, 0, (uint64)&de, off, sizeof(de)); de.sne.fst_clus_hi = (uint16)(entry->first_clus >> 16); - de.sne.fst_clus_lo = (uint16)(entry->first_clus & 0xff); + de.sne.fst_clus_lo = (uint16)(entry->first_clus & 0xffff); de.sne.file_size = entry->file_size; rw_clus(entry->parent->cur_clus, 1, 0, (uint64)&de, off, sizeof(de)); - eunlock(entry->parent); entry->dirty = 0; } // caller must hold entry->lock +// caller must hold entry->parent->lock // remove the entry in its parent directory void eremove(struct dirent *entry) { + if (entry->valid != 1) { return; } uint entcnt = 0; - elock(entry->parent); uint32 off = entry->off; uint32 off2 = reloc_clus(entry->parent, off, 0); rw_clus(entry->parent->cur_clus, 0, 0, (uint64) &entcnt, off2, 1); @@ -611,7 +632,6 @@ void eremove(struct dirent *entry) off += 32; off2 = reloc_clus(entry->parent, off, 0); } - eunlock(entry->parent); entry->valid = -1; } @@ -626,6 +646,7 @@ void etrunc(struct dirent *entry) } entry->file_size = 0; entry->first_clus = 0; + entry->dirty = 1; } void elock(struct dirent *entry) @@ -659,7 +680,9 @@ void eput(struct dirent *entry) if (entry->valid == -1) { // this means some one has called eremove() etrunc(entry); } else { + elock(entry->parent); eupdate(entry); + eunlock(entry->parent); } releasesleep(&entry->lock); @@ -669,7 +692,9 @@ void eput(struct dirent *entry) acquire(&ecache.lock); entry->ref--; release(&ecache.lock); - eput(eparent); + if (entry->ref == 0) { + eput(eparent); + } return; } entry->ref--; @@ -851,9 +876,8 @@ static char *skipelem(char *path, char *name) int len = path - s; if (len > FAT32_MAX_FILENAME) { len = FAT32_MAX_FILENAME; - } else { - name[len] = 0; } + name[len] = 0; memmove(name, s, len); while (*path == '/') { path++; diff --git a/kernel/include/fat32.h b/kernel/include/fat32.h index c82c17ed8899e47d61562c845cfa6651e0844053..83ba428312220a77e1d1249109a2b81bb7fffd57 100644 --- a/kernel/include/fat32.h +++ b/kernel/include/fat32.h @@ -52,7 +52,9 @@ struct dirent { int fat32_init(void); struct dirent* dirlookup(struct dirent *entry, char *filename, uint *poff); -struct dirent* ealloc(struct dirent *dp, char *name, int dir); +char* formatname(char *name); +void emake(struct dirent *dp, struct dirent *ep, uint off); +struct dirent* ealloc(struct dirent *dp, char *name, int attr); struct dirent* edup(struct dirent *entry); void eupdate(struct dirent *entry); void etrunc(struct dirent *entry); diff --git a/kernel/include/sysnum.h b/kernel/include/sysnum.h index dc445f081678e5e998dba9f1a2cc7767609c9812..fb43d060ecfaab14a1681f6f712c4e2b5c4d5b60 100644 --- a/kernel/include/sysnum.h +++ b/kernel/include/sysnum.h @@ -27,5 +27,6 @@ #define SYS_dev 23 #define SYS_readdir 24 #define SYS_getcwd 25 +#define SYS_rename 26 #endif \ No newline at end of file diff --git a/kernel/syscall.c b/kernel/syscall.c index fda0199d14881225fbf9f8057a9c9f584e6a1f7a..d906609780e943c7983b65930e733a564e975512 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -115,6 +115,7 @@ extern uint64 sys_getcwd(void); extern uint64 sys_remove(void); extern uint64 sys_trace(void); extern uint64 sys_sysinfo(void); +extern uint64 sys_rename(void); static uint64 (*syscalls[])(void) = { [SYS_fork] sys_fork, @@ -142,6 +143,7 @@ static uint64 (*syscalls[])(void) = { [SYS_remove] sys_remove, [SYS_trace] sys_trace, [SYS_sysinfo] sys_sysinfo, + [SYS_rename] sys_rename, }; static char *sysnames[] = { @@ -170,6 +172,7 @@ static char *sysnames[] = { [SYS_remove] "remove", [SYS_trace] "trace", [SYS_sysinfo] "sysinfo", + [SYS_rename] "rename", }; void @@ -183,7 +186,7 @@ syscall(void) p->trapframe->a0 = syscalls[num](); // trace if ((p->tmask & (1 << num)) != 0) { - printf("pid %d: syscall %s -> %d\n", p->pid, sysnames[num], p->trapframe->a0); + printf("pid %d: %s -> %d\n", p->pid, sysnames[num], p->trapframe->a0); } } else { printf("pid %d %s: unknown sys call %d\n", diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 46d9a0e23d3fab8bf0662cd92ccdc60007131b0d..3fd28fa3c43ee88e4c9408e52b3c9079c7cdec47 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -122,7 +122,7 @@ sys_fstat(void) } static struct dirent* -create(char *path, short type) +create(char *path, short type, int mode) { struct dirent *ep, *dp; char name[FAT32_MAX_FILENAME + 1]; @@ -130,8 +130,16 @@ create(char *path, short type) if((dp = enameparent(path, name)) == NULL) return NULL; + if (type == T_DIR) { + mode = ATTR_DIRECTORY; + } else if (mode & O_RDONLY) { + mode = ATTR_READ_ONLY; + } else { + mode = 0; + } + elock(dp); - if ((ep = ealloc(dp, name, type == T_DIR)) == NULL) { + if ((ep = ealloc(dp, name, mode)) == NULL) { eunlock(dp); eput(dp); return NULL; @@ -139,8 +147,8 @@ create(char *path, short type) if ((type == T_DIR && !(ep->attribute & ATTR_DIRECTORY)) || (type == T_FILE && (ep->attribute & ATTR_DIRECTORY))) { - eput(ep); eunlock(dp); + eput(ep); eput(dp); return NULL; } @@ -164,7 +172,7 @@ sys_open(void) return -1; if(omode & O_CREATE){ - ep = create(path, T_FILE); + ep = create(path, T_FILE, omode); if(ep == NULL){ return -1; } @@ -189,16 +197,16 @@ sys_open(void) return -1; } + if(!(ep->attribute & ATTR_DIRECTORY) && (omode & O_TRUNC)){ + etrunc(ep); + } + f->type = FD_ENTRY; f->off = (omode & O_APPEND) ? ep->file_size : 0; f->ep = ep; f->readable = !(omode & O_WRONLY); f->writable = (omode & O_WRONLY) || (omode & O_RDWR); - if(!(ep->attribute & ATTR_DIRECTORY) && (omode & O_TRUNC)){ - etrunc(ep); - } - eunlock(ep); return fd; @@ -210,7 +218,7 @@ sys_mkdir(void) char path[FAT32_MAX_PATH]; struct dirent *ep; - if(argstr(0, path, FAT32_MAX_PATH) < 0 || (ep = create(path, T_DIR)) == 0){ + if(argstr(0, path, FAT32_MAX_PATH) < 0 || (ep = create(path, T_DIR, 0)) == 0){ return -1; } eunlock(ep); @@ -395,10 +403,94 @@ sys_remove(void) eput(ep); return -1; } + elock(ep->parent); // Will this lead to deadlock? eremove(ep); - + eunlock(ep->parent); eunlock(ep); eput(ep); return 0; -} \ No newline at end of file +} + +// Must hold too many locks at a time! It's possible to raise a deadlock. +// Because this op takes some steps, we can't promise +uint64 +sys_rename(void) +{ + char old[FAT32_MAX_PATH], new[FAT32_MAX_PATH]; + if (argstr(0, old, FAT32_MAX_PATH) < 0 || argstr(1, new, FAT32_MAX_PATH) < 0) { + return -1; + } + + struct dirent *src = NULL, *dst = NULL, *pdst = NULL; + int srclock = 0; + char *name; + if ((src = ename(old)) == NULL || (pdst = enameparent(new, old)) == NULL + || (name = formatname(old)) == NULL) { + goto fail; // src doesn't exist || dst parent doesn't exist || illegal new name + } + for (struct dirent *ep = pdst; ep != NULL; ep = ep->parent) { + if (ep == src) { // In what universe can we move a directory into its child? + goto fail; + } + } + + uint off; + elock(src); // must hold child's lock before acquiring parent's, because we do so in other similar cases + srclock = 1; + elock(pdst); + dst = dirlookup(pdst, name, &off); + if (dst != NULL) { + eunlock(pdst); + if (src == dst) { + goto fail; + } else if (src->attribute & dst->attribute & ATTR_DIRECTORY) { + elock(dst); + if (!isdirempty(dst)) { // it's ok to overwrite an empty dir + eunlock(dst); + goto fail; + } + elock(pdst); + } else { // src is not a dir || dst exists and is not an dir + goto fail; + } + } + + if (dst) { + eremove(dst); + eunlock(dst); + } + memmove(src->filename, name, FAT32_MAX_FILENAME); + emake(pdst, src, off); + if (src->parent != pdst) { + eunlock(pdst); + elock(src->parent); + } + eremove(src); + eunlock(src->parent); + struct dirent *psrc = src->parent; // src must not be root, or it won't pass the for-loop test + src->parent = edup(pdst); + src->off = off; + src->valid = 1; + eunlock(src); + + eput(psrc); + if (dst) { + eput(dst); + } + eput(pdst); + eput(src); + + return 0; + +fail: + if (srclock) + eunlock(src); + if (dst) + eput(dst); + if (pdst) + eput(pdst); + if (src) + eput(src); + return -1; +} diff --git a/kernel/trap.c b/kernel/trap.c index 0b4c54c707a16d41a95c0d3decb7c07de95fe0cb..edf79e1474bf2076f6062617d4cb82b00c58e1ed 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -83,7 +83,7 @@ usertrap(void) else { printf("\nusertrap(): unexpected scause %p pid=%d %s\n", r_scause(), p->pid, p->name); printf(" sepc=%p stval=%p\n", r_sepc(), r_stval()); - trapframedump(p->trapframe); + // trapframedump(p->trapframe); p->killed = 1; } diff --git a/xv6-user/mv.c b/xv6-user/mv.c new file mode 100644 index 0000000000000000000000000000000000000000..6dc2aa9d15f06e375844876410b15a2011b82a80 --- /dev/null +++ b/xv6-user/mv.c @@ -0,0 +1,53 @@ +#include "kernel/include/types.h" +#include "kernel/include/stat.h" +#include "kernel/include/fcntl.h" +#include "kernel/include/param.h" +#include "xv6-user/user.h" + +int main(int argc, char *argv[]) +{ + if (argc < 3) { + fprintf(2, "Usage: mv old_name new_name\n"); + exit(1); + } + + char src[MAXPATH]; + char dst[MAXPATH]; + strcpy(src, argv[1]); + strcpy(dst, argv[2]); + int fd = open(dst, O_RDONLY); + if (fd >= 0) { + struct stat st; + fstat(fd, &st); + close(fd); + if (st.type == T_DIR) { + char *ps, *pd; + for (ps = src + strlen(src) - 1; ps >= src; ps--) { // trim '/' in tail + if (*ps != '/') { + *(ps + 1) = '\0'; + break; + } + } + for (; ps >= src && *ps != '/'; ps--); + ps++; + pd = dst + strlen(dst); + *pd++ = '/'; + while (*ps) { + *pd++ = *ps++; + if (pd >= dst + MAXPATH) { + fprintf(2, "mv: fail! final dst path too long (exceed MAX=%d)!\n", MAXPATH); + exit(-1); + } + } + } else { + fprintf(2, "mv: fail! %s exists!\n", dst); + exit(-1); + } + } + printf("moving [%s] to [%s]\n", src, dst); + if (rename(src, dst) < 0) { + fprintf(2, "mv: fail to rename %s to %s!\n", src, dst); + exit(-1); + } + exit(0); +} \ No newline at end of file diff --git a/xv6-user/user.h b/xv6-user/user.h index 291fddf9ccfdb1e902479a87d140cd9d841c005a..cf17f7a5357fa92d089a9b652b146ae0b344eb77 100644 --- a/xv6-user/user.h +++ b/xv6-user/user.h @@ -7,27 +7,28 @@ int fork(void); int exit(int) __attribute__((noreturn)); int wait(int*); int pipe(int*); -int write(int, const void*, int); -int read(int, void*, int); -int close(int); -int kill(int); +int write(int fd, const void *buf, int len); +int read(int fd, void *buf, int len); +int close(int fd); +int kill(int pid); int exec(char*, char**); -int open(const char*, int); +int open(const char *filename, int mode); int fstat(int fd, struct stat*); -int mkdir(const char*); -int chdir(const char*); -int dup(int); +int mkdir(const char *dirname); +int chdir(const char *dirname); +int dup(int fd); int getpid(void); -char* sbrk(int); -int sleep(int); +char* sbrk(int size); +int sleep(int ticks); int uptime(void); int test_proc(int); int dev(int, short, short); int readdir(int fd, struct stat*); -int getcwd(char *); -int remove(char *); -int trace(int); +int getcwd(char *buf); +int remove(char *filename); +int trace(int mask); int sysinfo(struct sysinfo *); +int rename(char *old, char *new); // ulib.c int stat(const char*, struct stat*); diff --git a/xv6-user/usertests.c b/xv6-user/usertests.c index 17ef17b71c7da5a09aae2aeee47117e79838285b..de67e6b907ea43947a019882ca091cd2cbff3581 100644 --- a/xv6-user/usertests.c +++ b/xv6-user/usertests.c @@ -943,6 +943,7 @@ forkforkfork(char *s) close(open("stopforking", O_CREATE|O_RDWR)); wait(0); sleep(10); // one second + remove("stopforking"); } // regression test. does reparent() violate the parent-then-child @@ -1140,7 +1141,7 @@ createdelete(char *s) enum { N = 20, NCHILD=4 }; int pid, i, fd, pi; char name[32]; - char illegal[] = { '\"', '*', '/', ':', '<', '>', '?', '\\', '|' }; + char illegal[] = { '\"', '*', '/', ':', '<', '>', '?', '\\', '|', 0 }; for(pi = 0; pi < NCHILD; pi++){ pid = fork(); if(pid < 0){ @@ -1163,9 +1164,11 @@ createdelete(char *s) } if(i > 0 && (i % 2 ) == 0){ name[1] = '0' + (i / 2); - if(remove(name) < 0){ - printf("%s: remove failed\n", s); - exit(1); + if (strchr(illegal, name[1]) == 0) { + if(remove(name) < 0){ + printf("%s: remove failed\n", s); + exit(1); + } } } } @@ -1201,7 +1204,7 @@ createdelete(char *s) for(i = 0; i < N; i++){ for(pi = 0; pi < NCHILD; pi++){ - name[0] = 'p' + i; + name[0] = 'p' + pi; name[1] = '0' + i; remove(name); } @@ -2268,6 +2271,7 @@ bigargtest(char *s) exit(1); } close(fd); + remove("bigarg-ok"); } // what happens when the file system runs out of blocks? @@ -2665,7 +2669,7 @@ main(int argc, char *argv[]) {createdelete, "createdelete"}, // {linkremove, "linkremove"}, // {linktest, "linktest"}, - // {removeread, "removeread"}, + {removeread, "removeread"}, // {concreate, "concreate"}, {subdir, "subdir"}, {fourfiles, "fourfiles"}, diff --git a/xv6-user/usys.pl b/xv6-user/usys.pl index 69f30450c41c76273eee4ee314b27928be83a627..e48bcde27e1e3859f1a927345afba521d04fe02a 100755 --- a/xv6-user/usys.pl +++ b/xv6-user/usys.pl @@ -40,3 +40,4 @@ entry("getcwd"); entry("remove"); entry("trace"); entry("sysinfo"); +entry("rename");