nfs-ganesha 1.4

subr.c

Go to the documentation of this file.
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, &sect_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 */