home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / mysys / my_lib.c < prev    next >
C/C++ Source or Header  |  2000-08-31  |  17KB  |  612 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17.  
  18. /* TODO: check for overun of memory for names. */
  19. /*     Convert MSDOS-TIME to standar time_t */
  20.  
  21. #define USES_TYPES        /* sys/types is included */
  22. #include    "mysys_priv.h"
  23. #include    <m_string.h>
  24. #include    <my_dir.h>    /* Structs used by my_dir,includes sys/types */
  25. #include    "mysys_err.h"
  26. #if defined(HAVE_DIRENT_H)
  27. # include <dirent.h>
  28. # define NAMLEN(dirent) strlen((dirent)->d_name)
  29. #else
  30. # define dirent direct
  31. # define NAMLEN(dirent) (dirent)->d_namlen
  32. # if defined(HAVE_SYS_NDIR_H)
  33. #  include <sys/ndir.h>
  34. # endif
  35. # if defined(HAVE_SYS_DIR_H)
  36. #  include <sys/dir.h>
  37. # endif
  38. # if defined(HAVE_NDIR_H)
  39. #  include <ndir.h>
  40. # endif
  41. # if defined(MSDOS) || defined(__WIN__)
  42. # include <dos.h>
  43. # ifdef __BORLANDC__
  44. # include <dir.h>
  45. # endif
  46. # endif
  47. #endif
  48. #ifdef VMS
  49. #include <rms.h>
  50. #include <iodef.h>
  51. #include <descrip.h>
  52. #endif
  53. #if defined(THREAD) && defined(HAVE_READDIR_R)
  54. #define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
  55. #else
  56. #define READDIR(A,B,C) (!(C=readdir(A)))
  57. #endif
  58.  
  59.  
  60. #define STARTSIZE    ONCE_ALLOC_INIT*8  /* some mallocmargin */
  61.  
  62. static int    comp_names(struct fileinfo *a,struct fileinfo *b);
  63.  
  64.  
  65.     /* We need this because program don't know with malloc we used */
  66.  
  67. void my_dirend(MY_DIR *buffer)
  68. {
  69.   DBUG_ENTER("my_dirend");
  70.   if (buffer)
  71.     my_free((gptr) buffer,MYF(0));
  72.   DBUG_VOID_RETURN;
  73. } /* my_dirend */
  74.  
  75.  
  76.     /* Compare in sort of filenames */
  77.  
  78. static int comp_names(struct fileinfo *a, struct fileinfo *b)
  79. {
  80.   return (strcmp(a->name,b->name));
  81. } /* comp_names */
  82.  
  83.  
  84. #if !defined(MSDOS) && !defined(__WIN__)
  85.  
  86. MY_DIR    *my_dir(const char *path, myf MyFlags)
  87. {
  88.   DIR        *dirp;
  89.   struct dirent *dp;
  90.   struct fileinfo *fnames;
  91.   char           *buffer, *obuffer, *tempptr;
  92.   uint        fcnt,i,size,firstfcnt, maxfcnt,length;
  93.   char        tmp_path[FN_REFLEN+1],*tmp_file;
  94.   my_ptrdiff_t    diff;
  95.   bool        eof;
  96. #ifdef THREAD
  97.   char    dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
  98. #endif
  99.   DBUG_ENTER("my_dir");
  100.   DBUG_PRINT("my",("path: '%s' stat: %d  MyFlags: %d",path,MyFlags));
  101.  
  102. #if defined(THREAD) && !defined(HAVE_READDIR_R)
  103.   pthread_mutex_lock(&THR_LOCK_open);
  104. #endif
  105.  
  106.   dirp = opendir(directory_file_name(tmp_path,(my_string) path));
  107.   size = STARTSIZE;
  108.   if (dirp == NULL || ! (buffer = (char *) my_malloc(size, MyFlags)))
  109.     goto error;
  110.  
  111.   fcnt = 0;
  112.   tmp_file=strend(tmp_path);
  113.   firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
  114.     (sizeof(struct fileinfo) + FN_LEN);
  115.   fnames=   (struct fileinfo *) (buffer + sizeof(MY_DIR));
  116.   tempptr = (char *) (fnames + maxfcnt);
  117.  
  118. #ifdef THREAD
  119.   dp= (struct dirent*) dirent_tmp;
  120. #else
  121.   dp=0;
  122. #endif
  123.   eof=0;
  124.   for (;;)
  125.   {
  126.     while (fcnt < maxfcnt &&
  127.        !(eof= READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
  128.     {
  129.       bzero((gptr) (fnames+fcnt),sizeof(fnames[0])); /* for purify */
  130.       fnames[fcnt].name = tempptr;
  131.       tempptr = strmov(tempptr,dp->d_name) + 1;
  132.       if (MyFlags & MY_WANT_STAT)
  133.       {
  134.     VOID(strmov(tmp_file,dp->d_name));
  135.     VOID(my_stat(tmp_path, &fnames[fcnt].mystat, MyFlags));
  136.       }
  137.       ++fcnt;
  138.     }
  139.     if (eof)
  140.       break;
  141.     size += STARTSIZE; obuffer = buffer;
  142.     if (!(buffer = (char *) my_realloc((gptr) buffer, size,
  143.                        MyFlags | MY_FREE_ON_ERROR)))
  144.       goto error;            /* No memory */
  145.     length= (uint) (sizeof(struct fileinfo ) * firstfcnt);
  146.     diff=    PTR_BYTE_DIFF(buffer , obuffer) + (int) length;
  147.     fnames=  (struct fileinfo *) (buffer + sizeof(MY_DIR));
  148.     tempptr= ADD_TO_PTR(tempptr,diff,char*);
  149.     for (i = 0; i < maxfcnt; i++)
  150.       fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
  151.  
  152.     /* move filenames upp a bit */
  153.     maxfcnt += firstfcnt;
  154.     bmove_upp(tempptr,tempptr-length,
  155.           (uint) (tempptr- (char*) (fnames+maxfcnt)));
  156.   }
  157.  
  158.   (void) closedir(dirp);
  159.   {
  160.     MY_DIR * s = (MY_DIR *) buffer;
  161.     s->number_off_files = (uint) fcnt;
  162.     s->dir_entry = fnames;
  163.   }
  164.   if (!(MyFlags & MY_DONT_SORT))
  165.     qsort((void *) fnames, (size_s) fcnt, sizeof(struct fileinfo),
  166.       (qsort_cmp) comp_names);
  167. #if defined(THREAD) && !defined(HAVE_READDIR_R)
  168.   pthread_mutex_unlock(&THR_LOCK_open);
  169. #endif
  170.   DBUG_RETURN((MY_DIR *) buffer);
  171.  
  172.  error:
  173. #if defined(THREAD) && !defined(HAVE_READDIR_R)
  174.   pthread_mutex_unlock(&THR_LOCK_open);
  175. #endif
  176.   my_errno=errno;
  177.   if (dirp)
  178.     (void) closedir(dirp);
  179.   if (MyFlags & (MY_FAE+MY_WME))
  180.     my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
  181.   DBUG_RETURN((MY_DIR *) NULL);
  182. } /* my_dir */
  183.  
  184.  
  185. /*
  186.  * Convert from directory name to filename.
  187.  * On VMS:
  188.  *     xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
  189.  *     xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
  190.  * On UNIX, it's simple: just make sure there is a terminating /
  191.  
  192.  * Returns pointer to dst;
  193.  */
  194.  
  195. my_string directory_file_name (my_string dst, const char *src)
  196. {
  197. #ifndef VMS
  198.  
  199.   /* Process as Unix format: just remove test the final slash. */
  200.  
  201.   my_string end;
  202.  
  203.   if (src[0] == 0)
  204.     src= (char*) ".";                /* Use empty as current */
  205.   end=strmov(dst, src);
  206.   if (end[-1] != FN_LIBCHAR)
  207.   {
  208.     end[0]=FN_LIBCHAR;                /* Add last '/' */
  209.     end[1]='\0';
  210.   }
  211.   return dst;
  212.  
  213. #else    /* VMS */
  214.  
  215.   long slen;
  216.   long rlen;
  217.   my_string ptr, rptr;
  218.   char bracket;
  219.   struct FAB fab = cc$rms_fab;
  220.   struct NAM nam = cc$rms_nam;
  221.   char esa[NAM$C_MAXRSS];
  222.  
  223.   if (! src[0])
  224.     src="[.]";                    /* Empty is == current dir */
  225.  
  226.   slen = strlen (src) - 1;
  227.   if (src[slen] == FN_C_AFTER_DIR || src[slen] == FN_C_AFTER_DIR_2 ||
  228.       src[slen] == FN_DEVCHAR)
  229.   {
  230.     /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
  231.     fab.fab$l_fna = src;
  232.     fab.fab$b_fns = slen + 1;
  233.     fab.fab$l_nam = &nam;
  234.     fab.fab$l_fop = FAB$M_NAM;
  235.  
  236.     nam.nam$l_esa = esa;
  237.     nam.nam$b_ess = sizeof esa;
  238.     nam.nam$b_nop |= NAM$M_SYNCHK;
  239.  
  240.     /* We call SYS$PARSE to handle such things as [--] for us. */
  241.     if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
  242.     {
  243.       slen = nam.nam$b_esl - 1;
  244.       if (esa[slen] == ';' && esa[slen - 1] == '.')
  245.     slen -= 2;
  246.       esa[slen + 1] = '\0';
  247.       src = esa;
  248.     }
  249.     if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2)
  250.     {
  251.     /* what about when we have logical_name:???? */
  252.       if (src[slen] == FN_DEVCHAR)
  253.       {                /* Xlate logical name and see what we get */
  254.     VOID(strmov(dst,src));
  255.     dst[slen] = 0;                /* remove colon */
  256.     if (!(src = getenv (dst)))
  257.       return dst;                /* Can't translate */
  258.  
  259.     /* should we jump to the beginning of this procedure?
  260.        Good points: allows us to use logical names that xlate
  261.        to Unix names,
  262.        Bad points: can be a problem if we just translated to a device
  263.        name...
  264.        For now, I'll punt and always expect VMS names, and hope for
  265.        the best! */
  266.  
  267.     slen = strlen (src) - 1;
  268.     if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2)
  269.     {                    /* no recursion here! */
  270.       VOID(strmov(dst, src));
  271.       return(dst);
  272.     }
  273.       }
  274.       else
  275.       {                        /* not a directory spec */
  276.     VOID(strmov(dst, src));
  277.     return(dst);
  278.       }
  279.     }
  280.  
  281.     bracket = src[slen];            /* End char */
  282.     if (!(ptr = strchr (src, bracket - 2)))
  283.     {                        /* no opening bracket */
  284.       VOID(strmov (dst, src));
  285.       return dst;
  286.     }
  287.     if (!(rptr = strrchr (src, '.')))
  288.       rptr = ptr;
  289.     slen = rptr - src;
  290.     VOID(strmake (dst, src, slen));
  291.  
  292.     if (*rptr == '.')
  293.     {                        /* Put bracket and add */
  294.       dst[slen++] = bracket;            /* (rptr+1) after this */
  295.     }
  296.     else
  297.     {
  298.       /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
  299.      then translate the device and recurse. */
  300.  
  301.       if (dst[slen - 1] == ':'
  302.       && dst[slen - 2] != ':'     /* skip decnet nodes */
  303.       && strcmp(src + slen, "[000000]") == 0)
  304.       {
  305.     dst[slen - 1] = '\0';
  306.     if ((ptr = getenv (dst))
  307.         && (rlen = strlen (ptr) - 1) > 0
  308.         && (ptr[rlen] == FN_C_AFTER_DIR || ptr[rlen] == FN_C_AFTER_DIR_2)
  309.         && ptr[rlen - 1] == '.')
  310.     {
  311.       VOID(strmov(esa,ptr));
  312.       esa[rlen - 1] = FN_C_AFTER_DIR;
  313.       esa[rlen] = '\0';
  314.       return (directory_file_name (dst, esa));
  315.     }
  316.     else
  317.       dst[slen - 1] = ':';
  318.       }
  319.       VOID(strmov(dst+slen,"[000000]"));
  320.       slen += 8;
  321.     }
  322.     VOID(strmov(strmov(dst+slen,rptr+1)-1,".DIR.1"));
  323.     return dst;
  324.   }
  325.   VOID(strmov(dst, src));
  326.   if (dst[slen] == '/' && slen > 1)
  327.     dst[slen] = 0;
  328.   return dst;
  329. #endif    /* VMS */
  330. } /* directory_file_name */
  331.  
  332. #elif defined(WIN32)
  333.  
  334. /*
  335. *****************************************************************************
  336. ** Read long filename using windows rutines
  337. *****************************************************************************
  338. */
  339.  
  340. MY_DIR    *my_dir(path, MyFlags)
  341. const char    *path;
  342. myf    MyFlags;
  343. {
  344.   struct fileinfo *fnames;
  345.   char           *buffer, *obuffer, *tempptr;
  346.   int        eof,i,fcnt,firstfcnt,length,maxfcnt;
  347.   uint        size;
  348. #ifdef __BORLANDC__
  349.   struct ffblk       find;
  350. #else
  351.   struct _finddata_t find;
  352. #endif
  353.   ushort    mode;
  354.   char        tmp_path[FN_REFLEN],*tmp_file,attrib;
  355.   my_ptrdiff_t    diff;
  356. #ifdef _WIN64
  357.   __int64       handle;
  358. #else
  359.   long        handle;
  360. #endif
  361.   DBUG_ENTER("my_dir");
  362.   DBUG_PRINT("my",("path: '%s' stat: %d  MyFlags: %d",path,MyFlags));
  363.  
  364.   /* Put LIB-CHAR as last path-character if not there */
  365.  
  366.   tmp_file=tmp_path;
  367.   if (!*path)
  368.     *tmp_file++ ='.';                /* From current dir */
  369.   tmp_file= strmov(tmp_file,path);
  370.   if (tmp_file[-1] == FN_DEVCHAR)
  371.     *tmp_file++= '.';                /* From current dev-dir */
  372.   if (tmp_file[-1] != FN_LIBCHAR)
  373.     *tmp_file++ =FN_LIBCHAR;
  374.   tmp_file[0]='*';                /* MSDOS needs this !??? */
  375.   tmp_file[1]='.';
  376.   tmp_file[2]='*';
  377.   tmp_file[3]='\0';
  378.  
  379. #ifdef __BORLANDC__
  380.   if ((handle= findfirst(tmp_path,&find,0)) == -1L)
  381.     goto error;
  382. #else
  383.   if ((handle=_findfirst(tmp_path,&find)) == -1L)
  384.     goto error;
  385. #endif
  386.  
  387.   size = STARTSIZE;
  388.   firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
  389.     (sizeof(struct fileinfo) + FN_LEN);
  390.   if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
  391.     goto error;
  392.   fnames=   (struct fileinfo *) (buffer + sizeof(MY_DIR));
  393.   tempptr = (char *) (fnames + maxfcnt);
  394.  
  395.   fcnt = 0;
  396.   for (;;)
  397.   {
  398.     do
  399.     {
  400.       fnames[fcnt].name = tempptr;
  401. #ifdef __BORLANDC__
  402.       tempptr = strmov(tempptr,find.ff_name) + 1;
  403.       fnames[fcnt].mystat.st_size=find.ff_fsize;
  404.       fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
  405.       mode=MY_S_IREAD; attrib=find.ff_attrib;
  406. #else
  407.       tempptr = strmov(tempptr,find.name) + 1;
  408.       fnames[fcnt].mystat.st_size=find.size;
  409.       fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
  410.       mode=MY_S_IREAD; attrib=find.attrib;
  411. #endif
  412.       if (!(attrib & _A_RDONLY))
  413.     mode|=MY_S_IWRITE;
  414.       if (attrib & _A_SUBDIR)
  415.     mode|=MY_S_IFDIR;
  416.       fnames[fcnt].mystat.st_mode=mode;
  417. #ifdef __BORLANDC__
  418.       fnames[fcnt].mystat.st_mtime=((uint32) find.ff_ftime);
  419. #else
  420.       fnames[fcnt].mystat.st_mtime=((uint32) find.time_write);
  421. #endif
  422.       ++fcnt;
  423. #ifdef __BORLANDC__
  424.     } while ((eof= findnext(&find)) == 0 && fcnt < maxfcnt);
  425. #else
  426.     } while ((eof= _findnext(handle,&find)) == 0 && fcnt < maxfcnt);
  427. #endif
  428.  
  429.     DBUG_PRINT("test",("eof: %d  errno: %d",eof,errno));
  430.     if (eof)
  431.       break;
  432.     size += STARTSIZE; obuffer = buffer;
  433.     if (!(buffer = (char *) my_realloc((gptr) buffer, size,
  434.                        MyFlags | MY_FREE_ON_ERROR)))
  435.       goto error;
  436.     length= sizeof(struct fileinfo ) * firstfcnt;
  437.     diff=    PTR_BYTE_DIFF(buffer , obuffer) +length;
  438.     fnames=  (struct fileinfo *) (buffer + sizeof(MY_DIR));
  439.     tempptr= ADD_TO_PTR(tempptr,diff,char*);
  440.     for (i = 0; i < maxfcnt; i++)
  441.       fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
  442.  
  443.     /* move filenames upp a bit */
  444.     maxfcnt += firstfcnt;
  445.     bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*),
  446.           (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt));
  447.   }
  448.   {
  449.     MY_DIR * s = (MY_DIR *) buffer;
  450.     s->number_off_files = (uint) fcnt;
  451.     s->dir_entry = fnames;
  452.   }
  453.   if (!(MyFlags & MY_DONT_SORT))
  454.     qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names);
  455. #ifndef __BORLANDC__
  456.   _findclose(handle);
  457. #endif
  458.   DBUG_RETURN((MY_DIR *) buffer);
  459.  
  460. error:
  461.   my_errno=errno;
  462. #ifndef __BORLANDC__
  463.   if (handle != -1)
  464.       _findclose(handle);
  465. #endif
  466.   if (MyFlags & MY_FAE+MY_WME)
  467.     my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
  468.   DBUG_RETURN((MY_DIR *) NULL);
  469. } /* my_dir */
  470.  
  471. #else /* MSDOS and not WIN32 */
  472.  
  473.  
  474. /******************************************************************************
  475. ** At MSDOS you always get stat of files, but time is in packed MSDOS-format
  476. ******************************************************************************/
  477.  
  478. MY_DIR    *my_dir(path, MyFlags)
  479. const char    *path;
  480. myf    MyFlags;
  481. {
  482.   struct fileinfo *fnames;
  483.   char           *buffer, *obuffer, *tempptr;
  484.   int        eof,i,fcnt,firstfcnt,length,maxfcnt;
  485.   uint        size;
  486.   struct find_t find;
  487.   ushort    mode;
  488.   char        tmp_path[FN_REFLEN],*tmp_file,attrib;
  489.   my_ptrdiff_t    diff;
  490.   DBUG_ENTER("my_dir");
  491.   DBUG_PRINT("my",("path: '%s' stat: %d  MyFlags: %d",path,MyFlags));
  492.  
  493.   /* Put LIB-CHAR as last path-character if not there */
  494.  
  495.   tmp_file=tmp_path;
  496.   if (!*path)
  497.     *tmp_file++ ='.';                /* From current dir */
  498.   tmp_file= strmov(tmp_file,path);
  499.   if (tmp_file[-1] == FN_DEVCHAR)
  500.     *tmp_file++= '.';                /* From current dev-dir */
  501.   if (tmp_file[-1] != FN_LIBCHAR)
  502.     *tmp_file++ =FN_LIBCHAR;
  503.   tmp_file[0]='*';                /* MSDOS needs this !??? */
  504.   tmp_file[1]='.';
  505.   tmp_file[2]='*';
  506.   tmp_file[3]='\0';
  507.  
  508.   if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find))
  509.     goto error;
  510.  
  511.   size = STARTSIZE;
  512.   firstfcnt = maxfcnt = (size - sizeof(MY_DIR)) /
  513.     (sizeof(struct fileinfo) + FN_LEN);
  514.   if ((buffer = (char *) my_malloc(size, MyFlags)) == 0)
  515.     goto error;
  516.   fnames=   (struct fileinfo *) (buffer + sizeof(MY_DIR));
  517.   tempptr = (char *) (fnames + maxfcnt);
  518.  
  519.   fcnt = 0;
  520.   for (;;)
  521.   {
  522.     do
  523.     {
  524.       fnames[fcnt].name = tempptr;
  525.       tempptr = strmov(tempptr,find.name) + 1;
  526.       fnames[fcnt].mystat.st_size=find.size;
  527.       fnames[fcnt].mystat.st_uid=fnames[fcnt].mystat.st_gid=0;
  528.       mode=MY_S_IREAD; attrib=find.attrib;
  529.       if (!(attrib & _A_RDONLY))
  530.     mode|=MY_S_IWRITE;
  531.       if (attrib & _A_SUBDIR)
  532.     mode|=MY_S_IFDIR;
  533.       fnames[fcnt].mystat.st_mode=mode;
  534.       fnames[fcnt].mystat.st_mtime=((uint32) find.wr_date << 16) +
  535.                          find.wr_time;
  536.       ++fcnt;
  537.     } while ((eof= _dos_findnext(&find)) == 0 && fcnt < maxfcnt);
  538.  
  539.     DBUG_PRINT("test",("eof: %d  errno: %d",eof,errno));
  540.     if (eof)
  541.       break;
  542.     size += STARTSIZE; obuffer = buffer;
  543.     if (!(buffer = (char *) my_realloc((gptr) buffer, size,
  544.                        MyFlags | MY_FREE_ON_ERROR)))
  545.       goto error;
  546.     length= sizeof(struct fileinfo ) * firstfcnt;
  547.     diff=    PTR_BYTE_DIFF(buffer , obuffer) +length;
  548.     fnames=  (struct fileinfo *) (buffer + sizeof(MY_DIR));
  549.     tempptr= ADD_TO_PTR(tempptr,diff,char*);
  550.     for (i = 0; i < maxfcnt; i++)
  551.       fnames[i].name = ADD_TO_PTR(fnames[i].name,diff,char*);
  552.  
  553.     /* move filenames upp a bit */
  554.     maxfcnt += firstfcnt;
  555.     bmove_upp(tempptr,ADD_TO_PTR(tempptr,-length,char*),
  556.           (int) PTR_BYTE_DIFF(tempptr,fnames+maxfcnt));
  557.   }
  558.   {
  559.     MY_DIR * s = (MY_DIR *) buffer;
  560.     s->number_off_files = (uint) fcnt;
  561.     s->dir_entry = fnames;
  562.   }
  563.   if (!(MyFlags & MY_DONT_SORT))
  564.     qsort(fnames,fcnt,sizeof(struct fileinfo),(qsort_cmp) comp_names);
  565.   DBUG_RETURN((MY_DIR *) buffer);
  566.  
  567. error:
  568.   if (MyFlags & MY_FAE+MY_WME)
  569.     my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
  570.   DBUG_RETURN((MY_DIR *) NULL);
  571. } /* my_dir */
  572.  
  573. #endif /* WIN32 && MSDOS */
  574.  
  575. /****************************************************************************
  576. ** File status
  577. ** Note that MY_STAT is assumed to be same as struct stat
  578. ****************************************************************************/ 
  579.  
  580. int my_fstat(int Filedes, MY_STAT *stat_area, myf MyFlags )
  581. {
  582.   DBUG_ENTER("my_fstat");
  583.   DBUG_PRINT("my",("fd: %d MyFlags: %d",Filedes,MyFlags));
  584.   DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area));
  585. }
  586.  
  587. MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
  588. {
  589.   int m_used;
  590.   DBUG_ENTER("my_stat");
  591.   DBUG_PRINT("my", ("path: '%s', stat_area: %lx, MyFlags: %d", path,
  592.          (byte *) stat_area, my_flags));
  593.  
  594.   if ((m_used= (stat_area == NULL)))
  595.     if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
  596.       goto error;
  597.   if ( ! stat((my_string) path, (struct stat *) stat_area) )
  598.     DBUG_RETURN(stat_area);
  599.   my_errno=errno;
  600.   if (m_used)                    /* Free if new area */
  601.     my_free((gptr) stat_area,MYF(0));
  602.  
  603. error:
  604.   if (my_flags & (MY_FAE+MY_WME))
  605.   {
  606.     my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),path,my_errno);
  607.     DBUG_RETURN((MY_STAT *) NULL);
  608.   }
  609.   DBUG_RETURN((MY_STAT *) NULL);
  610. } /* my_stat */
  611.  
  612.