nfs-ganesha 1.4
|
00001 /* 00002 * @(#)subr.c 1.6 03/12/29 Connectathon Testsuite 00003 * 1.6 Lachman ONC Test Suite source 00004 * 00005 * Useful subroutines shared by all tests 00006 */ 00007 00008 #if defined (DOS) || defined (WIN32) 00009 /* If Dos, Windows or Win32 */ 00010 #define DOSorWIN32 00011 #endif 00012 00013 #ifdef DOSorWIN32 00014 #include <io.h> 00015 #include <direct.h> 00016 #else 00017 #include <sys/param.h> 00018 #include <unistd.h> 00019 #endif 00020 00021 #include <sys/types.h> 00022 #include <sys/timeb.h> 00023 00024 #ifdef DOSorWIN32 00025 #include <time.h> 00026 #else 00027 #include <sys/time.h> 00028 #endif 00029 #include <sys/stat.h> 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 #include <string.h> 00033 #ifdef STDARG 00034 #include <stdarg.h> 00035 #endif 00036 00037 #include <unistd.h> 00038 #include <fcntl.h> 00039 00040 #include "tests.h" 00041 00042 char *Myname; 00043 int Dflag = 0; 00044 00045 int unix_mkdir(char *path, mode_t mode); 00046 int unix_chdir(char *path); 00047 00048 static void chdrive ARGS_((char *path)); 00049 /* 00050 * Build a directory tree "lev" levels deep 00051 * with "files" number of files in each directory 00052 * and "dirs" fan out. Starts at the current directory. 00053 * "fname" and "dname" are the base of the names used for 00054 * files and directories. 00055 */ 00056 void dirtree(lev, files, dirs, fname, dname, totfiles, totdirs) 00057 int lev; 00058 int files; 00059 int dirs; 00060 char *fname; 00061 char *dname; 00062 int *totfiles; 00063 int *totdirs; 00064 { 00065 int fd; 00066 int f, d; 00067 char name[MAXPATHLEN]; 00068 00069 if(lev-- == 0) 00070 { 00071 return; 00072 } 00073 for(f = 0; f < files; f++) 00074 { 00075 if(Dflag == 0) 00076 sprintf(name, "%s%d", fname, f); 00077 else 00078 sprintf(name, "%s%d.%d", fname, lev, f); 00079 if((fd = creat(name, CHMOD_RW)) < 0) 00080 { 00081 error("creat %s failed", name); 00082 exit(1); 00083 } 00084 (*totfiles)++; 00085 if(close(fd) < 0) 00086 { 00087 error("close %d failed", fd); 00088 exit(1); 00089 } 00090 } 00091 for(d = 0; d < dirs; d++) 00092 { 00093 if(Dflag == 0) 00094 sprintf(name, "%s%d", dname, d); 00095 else 00096 sprintf(name, "%s%d.%d", dname, lev, d); 00097 if(unix_mkdir(name, 0777) < 0) 00098 { 00099 error("mkdir %s failed", name); 00100 exit(1); 00101 } 00102 (*totdirs)++; 00103 if(unix_chdir(name) < 0) 00104 { 00105 error("chdir %s failed", name); 00106 exit(1); 00107 } 00108 dirtree(lev, files, dirs, fname, dname, totfiles, totdirs); 00109 if(unix_chdir("..") < 0) 00110 { 00111 error("chdir .. failed"); 00112 exit(1); 00113 } 00114 } 00115 } 00116 00117 /* 00118 * Remove a directory tree starting at the current directory. 00119 * "fname" and "dname" are the base of the names used for 00120 * files and directories to be removed - don't remove anything else! 00121 * "files" and "dirs" are used with fname and dname to generate 00122 * the file names to remove. 00123 * 00124 * This routine will fail if, say after removing known files, 00125 * the directory is not empty. 00126 * 00127 * This is used to test the unlink function and to clean up after tests. 00128 */ 00129 void rmdirtree(lev, files, dirs, fname, dname, totfiles, totdirs, ignore) 00130 int lev; 00131 int files; 00132 int dirs; 00133 char *fname; 00134 char *dname; 00135 int *totfiles; /* total removed */ 00136 int *totdirs; /* total removed */ 00137 int ignore; 00138 { 00139 int f, d; 00140 char name[MAXPATHLEN]; 00141 00142 if(lev-- == 0) 00143 { 00144 return; 00145 } 00146 for(f = 0; f < files; f++) 00147 { 00148 if(Dflag == 0) 00149 sprintf(name, "%s%d", fname, f); 00150 else 00151 sprintf(name, "%s%d.%d", fname, lev, f); 00152 if(unlink(name) < 0 && !ignore) 00153 { 00154 error("unlink %s failed", name); 00155 exit(1); 00156 } 00157 (*totfiles)++; 00158 } 00159 for(d = 0; d < dirs; d++) 00160 { 00161 if(Dflag == 0) 00162 sprintf(name, "%s%d", dname, d); 00163 else 00164 sprintf(name, "%s%d.%d", dname, lev, d); 00165 if(unix_chdir(name) < 0) 00166 { 00167 if(ignore) 00168 continue; 00169 error("chdir %s failed", name); 00170 exit(1); 00171 } 00172 rmdirtree(lev, files, dirs, fname, dname, totfiles, totdirs, ignore); 00173 if(unix_chdir("..") < 0) 00174 { 00175 error("chdir .. failed"); 00176 exit(1); 00177 } 00178 if(rmdir(name) < 0) 00179 { 00180 error("rmdir %s failed", name); 00181 exit(1); 00182 } 00183 (*totdirs)++; 00184 } 00185 } 00186 00187 #ifdef STDARG 00188 void error(char *str, ...) 00189 { 00190 int oerrno; 00191 char *ret; 00192 char path[MAXPATHLEN]; 00193 va_list ap; 00194 00195 oerrno = errno; 00196 00197 va_start(ap, str); 00198 if((ret = getcwd(path, sizeof(path))) == NULL) 00199 fprintf(stderr, "%s: getcwd failed\n", Myname); 00200 else 00201 fprintf(stderr, "\t%s: (%s) ", Myname, path); 00202 vfprintf(stderr, str, ap); 00203 va_end(ap); 00204 00205 if(oerrno) 00206 { 00207 errno = oerrno; 00208 perror(" "); 00209 } 00210 else 00211 { 00212 fprintf(stderr, "\n"); 00213 } 00214 fflush(stderr); 00215 if(ret == NULL) 00216 exit(1); 00217 } 00218 #else 00219 /* VARARGS */ 00220 error(str, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9) 00221 char *str; 00222 { 00223 int oerrno; 00224 char *ret; 00225 char path[MAXPATHLEN]; 00226 00227 oerrno = errno; 00228 if((ret = getcwd(path, sizeof(path))) == NULL) 00229 fprintf(stderr, "%s: getcwd failed\n", Myname); 00230 else 00231 fprintf(stderr, "\t%s: (%s) ", Myname, path); 00232 00233 fprintf(stderr, str, ar1, ar2, ar3, ar4, ar5, ar6, ar7, ar8, ar9); 00234 if(oerrno) 00235 { 00236 errno = oerrno; 00237 perror(" "); 00238 } 00239 else 00240 { 00241 fprintf(stderr, "\n"); 00242 } 00243 fflush(stderr); 00244 if(ret == NULL) 00245 exit(1); 00246 } 00247 #endif /* STDARG */ 00248 00249 static struct timeval ts, te; 00250 00251 /* 00252 * save current time in struct ts 00253 */ 00254 void starttime() 00255 { 00256 00257 gettimeofday(&ts, (struct timezone *)0); 00258 } 00259 00260 /* 00261 * sets the struct tv to the difference in time between 00262 * current time and the time in struct ts. 00263 */ 00264 void endtime(tv) 00265 struct timeval *tv; 00266 { 00267 00268 gettimeofday(&te, (struct timezone *)0); 00269 if(te.tv_usec < ts.tv_usec) 00270 { 00271 te.tv_sec--; 00272 te.tv_usec += 1000000; 00273 } 00274 tv->tv_usec = te.tv_usec - ts.tv_usec; 00275 tv->tv_sec = te.tv_sec - ts.tv_sec; 00276 #ifdef DOS 00277 /* 00278 * DOS uses time since midnight, so it could go negative if the 00279 * test spans midnight. If that happens, add a day. 00280 */ 00281 if(tv->tv_sec < 0) 00282 tv->tv_sec += 24 * 3600; 00283 #endif 00284 } 00285 00286 /* 00287 * Set up and move to a test directory 00288 */ 00289 void testdir(dir) 00290 char *dir; 00291 { 00292 struct stat statb; 00293 char str[MAXPATHLEN]; 00294 00295 /* 00296 * If dir is non-NULL, use that dir. If NULL, first 00297 * check for env variable NFSTESTDIR. If that is not 00298 * set, use the compiled-in TESTDIR. 00299 */ 00300 if(dir == NULL) 00301 { 00302 error("Non specified test directory"); 00303 exit(1); 00304 } 00305 00306 if(stat(dir, &statb) == 0) 00307 { 00308 sprintf(str, "rm -r %s", dir); 00309 #ifdef WIN16 00310 if(rmdir(dir) < 0) 00311 { 00312 #else 00313 if(system(str) != 0) 00314 { 00315 #endif 00316 error("can't remove old test directory %s", dir); 00317 exit(1); 00318 } 00319 } 00320 00321 if(unix_mkdir(dir, 0777) < 0) 00322 { 00323 error("can't create test directory %s", dir); 00324 exit(1); 00325 } 00326 if(unix_chdir(dir) < 0) 00327 { 00328 error("can't chdir to test directory %s", dir); 00329 exit(1); 00330 } 00331 } 00332 00333 /* 00334 * Move to a test directory 00335 */ 00336 int mtestdir(dir) 00337 char *dir; 00338 { 00339 /* 00340 * If dir is non-NULL, use that dir. If NULL, first 00341 * check for env variable NFSTESTDIR. If that is not 00342 * set, use the compiled-in TESTDIR. 00343 */ 00344 if(dir == NULL) 00345 { 00346 error("Non specified test directory"); 00347 exit(1); 00348 } 00349 00350 if(unix_chdir(dir) < 0) 00351 { 00352 error("can't chdir to test directory %s", dir); 00353 return (-1); 00354 } 00355 return (0); 00356 } 00357 00358 /* 00359 * get parameter at parm, convert to int, and make sure that 00360 * it is at least min. 00361 */ 00362 long getparm(parm, min, label) 00363 char *parm; 00364 long min; 00365 char *label; 00366 { 00367 long val; 00368 00369 val = atol(parm); 00370 if(val < min) 00371 { 00372 error("Illegal %s parameter %ld, must be at least %ld", label, val, min); 00373 exit(1); 00374 } 00375 return (val); 00376 } 00377 00378 /* 00379 * exit point for successful test 00380 */ 00381 void complete() 00382 { 00383 00384 fprintf(stdout, "\t%s ok.\n", Myname); 00385 chdrive(Myname); 00386 exit(0); 00387 } 00388 00389 /* 00390 * Change to drive specified in path 00391 */ 00392 int unix_chdir(path) 00393 char *path; 00394 { 00395 chdrive(path); 00396 return chdir(path); 00397 } 00398 00399 #ifndef DOSorWIN32 00400 00401 static void chdrive(path) 00402 char *path; 00403 { 00404 } 00405 00406 int unix_mkdir(path, mode) 00407 char *path; 00408 mode_t mode; 00409 { 00410 return mkdir(path, mode); 00411 } 00412 00413 #endif /* DOSorWIN32 */ 00414 00415 #ifdef NEED_STRERROR 00416 /* 00417 * Hack replacement for strerror(). This could be made to include useful 00418 * error strings, but it will do for the time being. 00419 */ 00420 char *strerror(errval) 00421 int errval; /* errno value */ 00422 { 00423 static char buf[1024]; 00424 00425 sprintf(buf, "error %d", errval); 00426 return (buf); 00427 } 00428 #endif /* NEED_STRERROR */ 00429 00430 /***********************************************************/ 00431 /* The following routines were ADDED specifically for */ 00432 /* DOS AND WIN32. */ 00433 /***********************************************************/ 00434 00435 #ifdef DOSorWIN32 00436 00437 /* 00438 * Return file statistics for the path specified 00439 */ 00440 00441 int lstat(char *path, struct stat *buf) 00442 { 00443 return stat(path, buf); 00444 } 00445 00446 int unix_mkdir(const char *path, int mode) 00447 { 00448 mode = mode; /* keep lint, compiler happy */ 00449 return mkdir(path); 00450 } 00451 00452 #endif /* DOSorWIN32 */ 00453 00454 /************************************************************/ 00455 /* The following routines were ADDED specifically for WIN32.*/ 00456 /************************************************************/ 00457 00458 #ifdef WIN32 00459 00460 /* 00461 * Change to drive specified in path 00462 */ 00463 static void chdrive(char *path) 00464 { 00465 int desireddrive; 00466 00467 if(path[1] == ':') 00468 { 00469 desireddrive = toupper(path[0]) - ('A' - 1); 00470 if(_chdrive(desireddrive)) 00471 { 00472 error("can't change to drive %c:", path[0]); 00473 exit(1); 00474 } 00475 } 00476 } 00477 00478 void gettimeofday(struct timeval *TV, struct timezone *TimeZone) 00479 { 00480 struct _timeb dostime; 00481 00482 _ftime(&dostime); 00483 TV->tv_sec = dostime.time; 00484 TV->tv_usec = dostime.millitm * 1000L; 00485 TimeZone = TimeZone; /* shut up compiler/lint */ 00486 } 00487 00488 int statfs(char *path, struct statfs *buf) 00489 { 00490 char *p = (char *)buf; 00491 int i; 00492 unsigned drive; 00493 00494 unsigned sect_per_clust; 00495 unsigned bytes_per_sect; 00496 unsigned free_clust; 00497 unsigned clust; 00498 char rootpath[MAXPATHLEN]; 00499 00500 for(i = 0; i < sizeof(*buf); i++) 00501 *p++ = (char)-1; 00502 buf->f_type = 0; /* that's what the man page says */ 00503 if(path[1] == ':') 00504 drive = toupper(path[0]) - ('A' - 1); 00505 else 00506 drive = _getdrive(); 00507 00508 // GetDiskFreeSpace must have the #$%^&* root! 00509 // be simple-minded: must be "d:<whatever>" 00510 strcpy(rootpath, path); 00511 p = strtok(rootpath, "\\"); 00512 *p++ = '\\'; 00513 *p = '\0'; 00514 if(!GetDiskFreeSpace(rootpath, §_per_clust, &bytes_per_sect, &free_clust, &clust)) 00515 { 00516 printf("GetDiskFreeSpace failed\n"); 00517 return -1; 00518 } 00519 buf->f_bsize = bytes_per_sect; 00520 buf->f_blocks = clust * sect_per_clust; 00521 buf->f_bfree = free_clust * sect_per_clust; 00522 buf->f_bavail = buf->f_bfree; 00523 00524 return 0; 00525 } 00526 00527 /*************************************************************** 00528 DIRENT emulation for Win32 00529 ***************************************************************/ 00530 char pattern[MAXNAMLEN]; 00531 struct _finddata_t findtst; 00532 long findhandle; 00533 int maxentry; 00534 int currententry; 00535 int diropen = 0; 00536 struct dirent *dirlist; 00537 DIR dirst; 00538 00539 static void copynametolower(char *dest, char *src); 00540 static void findt_to_dirent(struct dirent *d); 00541 static int win32_findfirst(char *pattern); 00542 static int win32_findnext(void); 00543 00544 int win32_findfirst(char *pattern) 00545 { 00546 findhandle = _findfirst(pattern, &findtst); 00547 return findhandle == -1; 00548 } 00549 00550 int win32_findnext(void) 00551 { 00552 return _findnext(findhandle, &findtst); 00553 } 00554 00555 int win32_findclose(void) 00556 { 00557 return _findclose(findhandle); 00558 } 00559 00560 DIR *opendir(char *dirname) 00561 { 00562 int i; 00563 00564 strcpy(pattern, dirname); 00565 strcat(pattern, "\\*.*"); 00566 if(diropen) 00567 return NULL; 00568 diropen = 1; 00569 dirlist = (struct dirent *)malloc(512 * sizeof(struct dirent)); 00570 if(dirlist == NULL) 00571 return NULL; 00572 00573 if(win32_findfirst(pattern)) 00574 return NULL; 00575 findt_to_dirent(&dirlist[0]); 00576 for(i = 1; !win32_findnext(); i++) 00577 { 00578 findt_to_dirent(&dirlist[i]); 00579 } 00580 win32_findclose(); 00581 00582 maxentry = i - 1; 00583 currententry = 0; 00584 return &dirst; 00585 } 00586 00587 void rewinddir(DIR * dirp) 00588 { 00589 int i; 00590 unsigned int attributes = _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SUBDIR; 00591 00592 dirp = dirp; /* shut up compiler */ 00593 00594 if(win32_findfirst(pattern)) 00595 { 00596 error("rewind failed"); 00597 exit(1); 00598 } 00599 findt_to_dirent(&dirlist[0]); 00600 for(i = 1; !win32_findnext(); i++) 00601 { 00602 findt_to_dirent(&dirlist[i]); 00603 } 00604 win32_findclose(); 00605 00606 maxentry = i - 1; 00607 currententry = 0; 00608 } 00609 00610 long telldir(DIR * dirp) 00611 { 00612 dirp = dirp; /* keep compiler happy */ 00613 return (long)currententry; 00614 } 00615 00616 void seekdir(DIR * dirp, long loc) 00617 { 00618 dirp = dirp; /* keep compiler happy */ 00619 if(loc <= (long)maxentry) 00620 currententry = (int)loc; 00621 /* else seekdir silently fails */ 00622 } 00623 00624 struct dirent *readdir(DIR * dirp) 00625 { 00626 dirp = dirp; /* shut up compiler */ 00627 if(currententry > maxentry) 00628 return (struct dirent *)NULL; 00629 else 00630 { 00631 return &dirlist[currententry++]; 00632 } 00633 } 00634 00635 void findt_to_dirent(struct dirent *d) 00636 { 00637 copynametolower(d->d_name, findtst.name); 00638 } 00639 00640 static void copynametolower(char *dest, char *src) 00641 { 00642 int i; 00643 for(i = 0; dest[i] = (char)tolower((int)src[i]); i++) 00644 { 00645 /* null body */ 00646 } 00647 } 00648 00649 void closedir(DIR * dirp) 00650 { 00651 dirp = dirp; /* keep compiler happy */ 00652 diropen = 0; 00653 } 00654 00655 #endif /* WIN32 */ 00656 00657 /***********************************************************/ 00658 /* The following routines were ADDED specifically for DOS */ 00659 /***********************************************************/ 00660 00661 #if defined DOS 00662 00663 /* 00664 * Change to drive specified in path 00665 */ 00666 00667 static void chdrive(path) 00668 char *path; 00669 { 00670 int desireddrive, drive; 00671 if(path[1] == ':') 00672 { 00673 desireddrive = toupper(path[0]) - ('A' - 1); 00674 _dos_setdrive(desireddrive, &drive); 00675 _dos_getdrive(&drive); 00676 if(drive != desireddrive) 00677 { 00678 error("can't change to drive %c:", path[0]); 00679 exit(1); 00680 } 00681 } 00682 } 00683 00684 void gettimeofday(struct timeval *TV, struct timezone *TimeZone) 00685 { 00686 struct dostime_t dostime; 00687 00688 _dos_gettime(&dostime); 00689 TV->tv_sec = dostime.hour * 3600L + dostime.minute * 60L + dostime.second; 00690 TV->tv_usec = dostime.hsecond * 10000L; 00691 TimeZone = TimeZone; /* shut up compiler/lint */ 00692 } 00693 00694 int statfs(path, buf) 00695 char *path; 00696 struct statfs *buf; 00697 { 00698 char *p = (char *)buf; 00699 int i; 00700 unsigned drive; 00701 struct diskfree_t diskspace; 00702 00703 for(i = 0; i < sizeof(*buf); i++) 00704 *p++ = (char)-1; 00705 buf->f_type = 0; /* that's what the man page says */ 00706 if(path[1] == ':') 00707 drive = toupper(path[0]) - ('A' - 1); 00708 else 00709 _dos_getdrive(&drive); 00710 if(_dos_getdiskfree(drive, &diskspace)) 00711 return -1; 00712 buf->f_bsize = diskspace.bytes_per_sector; 00713 buf->f_blocks = (long)diskspace.total_clusters * diskspace.sectors_per_cluster; 00714 buf->f_bfree = (long)diskspace.avail_clusters * diskspace.sectors_per_cluster; 00715 buf->f_bavail = buf->f_bfree; 00716 return 0; 00717 } 00718 00719 /*************************************************************** 00720 DIRENT emulation for DOS 00721 ***************************************************************/ 00722 char pattern[MAXNAMLEN]; 00723 struct find_t findtst; 00724 int maxentry; 00725 int currententry; 00726 int diropen = 0; 00727 struct dirent *dirlist; 00728 DIR dirst; 00729 00730 static void copynametolower(char *dest, char *src); 00731 static void findt_to_dirent(struct find_t *f, struct dirent *d); 00732 00733 DIR *opendir(dirname) 00734 char *dirname; 00735 { 00736 int i; 00737 unsigned int attributes = _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SUBDIR; 00738 00739 strcpy(pattern, dirname); 00740 strcat(pattern, "\\*.*"); 00741 if(diropen) 00742 return NULL; 00743 diropen = 1; 00744 dirlist = (struct dirent *)malloc(512 * sizeof(struct dirent)); 00745 if(dirlist == NULL) 00746 return NULL; 00747 if(_dos_findfirst(pattern, attributes, &findtst)) 00748 return NULL; 00749 findt_to_dirent(&findtst, &dirlist[0]); 00750 for(i = 1; !_dos_findnext(&findtst); i++) 00751 { 00752 findt_to_dirent(&findtst, &dirlist[i]); 00753 } 00754 maxentry = i - 1; 00755 currententry = 0; 00756 return &dirst; 00757 } 00758 00759 void rewinddir(dirp) 00760 DIR *dirp; 00761 { 00762 int i; 00763 unsigned int attributes = _A_NORMAL | _A_RDONLY | _A_HIDDEN | _A_SUBDIR; 00764 00765 dirp = dirp; /* shut up compiler */ 00766 if(_dos_findfirst(pattern, attributes, &findtst)) 00767 { 00768 error("rewind failed"); 00769 exit(1); 00770 } 00771 findt_to_dirent(&findtst, &dirlist[0]); 00772 for(i = 1; !_dos_findnext(&findtst); i++) 00773 { 00774 findt_to_dirent(&findtst, &dirlist[i]); 00775 } 00776 maxentry = i - 1; 00777 currententry = 0; 00778 } 00779 00780 long telldir(dirp) 00781 DIR *dirp; 00782 { 00783 dirp = dirp; /* keep compiler happy */ 00784 return (long)currententry; 00785 } 00786 00787 void seekdir(dirp, loc) 00788 DIR *dirp; 00789 long loc; 00790 { 00791 dirp = dirp; /* keep compiler happy */ 00792 if(loc <= (long)maxentry) 00793 currententry = (int)loc; 00794 /* else seekdir silently fails */ 00795 } 00796 00797 struct dirent *readdir(dirp) 00798 DIR *dirp; 00799 { 00800 dirp = dirp; /* shut up compiler */ 00801 if(currententry > maxentry) 00802 return (struct dirent *)NULL; 00803 else 00804 { 00805 return &dirlist[currententry++]; 00806 } 00807 } 00808 00809 void findt_to_dirent(f, d) 00810 struct find_t *f; 00811 struct dirent *d; 00812 { 00813 copynametolower(d->d_name, f->name); 00814 } 00815 00816 static void copynametolower(dest, src) 00817 char *dest; 00818 char *src; 00819 { 00820 int i; 00821 for(i = 0; dest[i] = (char)tolower((int)src[i]); i++) 00822 { 00823 /* null body */ 00824 } 00825 } 00826 00827 void closedir(dirp) 00828 DIR *dirp; 00829 { 00830 dirp = dirp; /* keep compiler happy */ 00831 diropen = 0; 00832 } 00833 00834 #endif /* DOS */