/* * test-lab-5 dir1 dir2 * * Creates and deletes files in different directories * on the same underlying file system. These operations * should not require much put/get or lock traffic in * a yfs with a write-back cache and lazy lock release. */ #include #include #include #include #include #include #include #include #include #include #include char d1[512], d2[512]; extern int errno; void create1(const char *d, const char *f, const char *in) { int fd; char n[512]; /* * The FreeBSD NFS client only invalidates its caches * cache if the mtime changes by a whole second. */ sleep(1); sprintf(n, "%s/%s", d, f); fd = creat(n, 0666); if(fd < 0){ fprintf(stderr, "test-lab-4-c: create(%s): %s\n", n, strerror(errno)); exit(1); } if(write(fd, in, strlen(in)) != strlen(in)){ fprintf(stderr, "test-lab-4-c: write(%s): %s\n", n, strerror(errno)); exit(1); } if(close(fd) != 0){ fprintf(stderr, "test-lab-4-c: close(%s): %s\n", n, strerror(errno)); exit(1); } } void check1(const char *d, const char *f, const char *in) { int fd, cc; char n[512], buf[512]; sprintf(n, "%s/%s", d, f); fd = open(n, 0); if(fd < 0){ fprintf(stderr, "test-lab-4-c: open(%s): %s\n", n, strerror(errno)); exit(1); } errno = 0; cc = read(fd, buf, sizeof(buf) - 1); if(cc != strlen(in)){ fprintf(stderr, "test-lab-4-c: read(%s) returned too little %d%s%s\n", n, cc, errno ? ": " : "", errno ? strerror(errno) : ""); exit(1); } close(fd); buf[cc] = '\0'; if(strncmp(buf, in, strlen(n)) != 0){ fprintf(stderr, "test-lab-4-c: read(%s) got \"%s\", not \"%s\"\n", n, buf, in); exit(1); } } void unlink1(const char *d, const char *f) { char n[512]; sleep(1); sprintf(n, "%s/%s", d, f); if(unlink(n) != 0){ fprintf(stderr, "test-lab-4-c: unlink(%s): %s\n", n, strerror(errno)); exit(1); } } void checknot(const char *d, const char *f) { int fd; char n[512]; sprintf(n, "%s/%s", d, f); fd = open(n, 0); if(fd >= 0){ fprintf(stderr, "test-lab-4-c: open(%s) succeeded for deleted file\n", n); exit(1); } } void append1(const char *d, const char *f, const char *in) { int fd; char n[512]; sleep(1); sprintf(n, "%s/%s", d, f); fd = open(n, O_WRONLY|O_APPEND); if(fd < 0){ fprintf(stderr, "test-lab-4-c: append open(%s): %s\n", n, strerror(errno)); exit(1); } if(write(fd, in, strlen(in)) != strlen(in)){ fprintf(stderr, "test-lab-4-c: append write(%s): %s\n", n, strerror(errno)); exit(1); } if(close(fd) != 0){ fprintf(stderr, "test-lab-4-c: append close(%s): %s\n", n, strerror(errno)); exit(1); } } void createn(const char *d, const char *prefix, int nf) { int fd, i; char n[512]; /* * The FreeBSD NFS client only invalidates its caches * cache if the mtime changes by a whole second. */ sleep(1); for(i = 0; i < nf; i++){ sprintf(n, "%s/%s-%d", d, prefix, i); fd = creat(n, 0666); if(fd < 0){ fprintf(stderr, "test-lab-4-c: create(%s): %s\n", n, strerror(errno)); exit(1); } if(write(fd, &i, sizeof(i)) != sizeof(i)){ fprintf(stderr, "test-lab-4-c: write(%s): %s\n", n, strerror(errno)); exit(1); } if(close(fd) != 0){ fprintf(stderr, "test-lab-4-c: close(%s): %s\n", n, strerror(errno)); exit(1); } } } void checkn(const char *d, const char *prefix, int nf) { int fd, i, cc, j; char n[512]; for(i = 0; i < nf; i++){ sprintf(n, "%s/%s-%d", d, prefix, i); fd = open(n, 0); if(fd < 0){ fprintf(stderr, "test-lab-4-c: open(%s): %s\n", n, strerror(errno)); exit(1); } j = -1; cc = read(fd, &j, sizeof(j)); if(cc != sizeof(j)){ fprintf(stderr, "test-lab-4-c: read(%s) returned too little %d%s%s\n", n, cc, errno ? ": " : "", errno ? strerror(errno) : ""); exit(1); } if(j != i){ fprintf(stderr, "test-lab-4-c: checkn %s contained %d not %d\n", n, j, i); exit(1); } close(fd); } } void unlinkn(const char *d, const char *prefix, int nf) { char n[512]; int i; sleep(1); for(i = 0; i < nf; i++){ sprintf(n, "%s/%s-%d", d, prefix, i); if(unlink(n) != 0){ fprintf(stderr, "test-lab-4-c: unlink(%s): %s\n", n, strerror(errno)); exit(1); } } } int compar(const void *xa, const void *xb) { char *a = *(char**)xa; char *b = *(char**)xb; return strcmp(a, b); } void dircheck(const char *d, int nf) { DIR *dp; struct dirent *e; char *names[1000]; int nnames = 0, i; dp = opendir(d); if(dp == 0){ fprintf(stderr, "test-lab-4-c: opendir(%s): %s\n", d, strerror(errno)); exit(1); } while((e = readdir(dp))){ if(e->d_name[0] != '.'){ if(nnames >= sizeof(names)/sizeof(names[0])){ fprintf(stderr, "warning: too many files in %s\n", d); } names[nnames] = (char *) malloc(strlen(e->d_name) + 1); strcpy(names[nnames], e->d_name); nnames++; } } closedir(dp); if(nf != nnames){ fprintf(stderr, "test-lab-4-c: wanted %d dir entries, got %d\n", nf, nnames); exit(1); } /* check for duplicate entries */ qsort(names, nnames, sizeof(names[0]), compar); for(i = 0; i < nnames-1; i++){ if(strcmp(names[i], names[i+1]) == 0){ fprintf(stderr, "test-lab-4-c: duplicate directory entry for %s\n", names[i]); exit(1); } } for(i = 0; i < nnames; i++) free(names[i]); } void reap (int pid) { int wpid, status; wpid = waitpid (pid, &status, 0); if (wpid < 0) { perror("waitpid"); exit(1); } if (wpid != pid) { fprintf(stderr, "unexpected pid reaped: %d\n", wpid); exit(1); } if(!WIFEXITED(status) || WEXITSTATUS(status) != 0) { fprintf(stderr, "child exited unhappily\n"); exit(1); } } int main(int argc, char *argv[]) { int pid; if(argc != 3){ fprintf(stderr, "Usage: test-lab-4-c dir1 dir2\n"); exit(1); } sprintf(d1, "%s/da%d", argv[1], getpid()); if(mkdir(d1, 0777) != 0){ fprintf(stderr, "test-lab-4-c: failed: mkdir(%s): %s\n", d1, strerror(errno)); exit(1); } sprintf(d2, "%s/db%d", argv[2], getpid()); if(mkdir(d2, 0777) != 0){ fprintf(stderr, "test-lab-4-c: failed: mkdir(%s): %s\n", d2, strerror(errno)); exit(1); } { char dd[512]; sprintf(dd, "%s/da%d", argv[2], getpid()); if(access(dd, 0) != 0){ fprintf(stderr, "test-lab-4-c: failed: access(%s) after mkdir %s: %s\n", dd, d1, strerror(errno)); exit(1); } } setbuf(stdout, 0); printf("Create/delete in separate directories: "); pid = fork(); if(pid < 0){ perror("test-lab-4-c: fork"); exit(1); } if(pid == 0){ createn(d2, "xx", 100); unlinkn(d2, "xx", 99); exit(0); } createn(d1, "yy", 100); unlinkn(d1, "yy", 99); sleep(4); reap(pid); dircheck(d1, 1); dircheck(d2, 1); printf("tests completed OK\n"); exit(0); return(0); }