my_lib.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:18k
- /* Copyright (C) 2000 MySQL AB
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
- /* TODO: check for overun of memory for names. */
- /* Convert MSDOS-TIME to standar time_t */
- #define USES_TYPES /* sys/types is included */
- #include "mysys_priv.h"
- #include <m_string.h>
- #include <my_dir.h> /* Structs used by my_dir,includes sys/types */
- #include "mysys_err.h"
- #if defined(HAVE_DIRENT_H)
- # include <dirent.h>
- # define NAMLEN(dirent) strlen((dirent)->d_name)
- #else
- #ifndef OS2
- # define dirent direct
- #endif
- # define NAMLEN(dirent) (dirent)->d_namlen
- # if defined(HAVE_SYS_NDIR_H)
- # include <sys/ndir.h>
- # endif
- # if defined(HAVE_SYS_DIR_H)
- # include <sys/dir.h>
- # endif
- # if defined(HAVE_NDIR_H)
- # include <ndir.h>
- # endif
- # if defined(MSDOS) || defined(__WIN__)
- # include <dos.h>
- # ifdef __BORLANDC__
- # include <dir.h>
- # endif
- # endif
- #endif
- #ifdef VMS
- #include <rms.h>
- #include <iodef.h>
- #include <descrip.h>
- #endif
- #ifdef OS2
- #include "my_os2dirsrch.h"
- #endif
- #if defined(THREAD) && defined(HAVE_READDIR_R)
- #define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
- #else
- #define READDIR(A,B,C) (!(C=readdir(A)))
- #endif
- /*
- We are assuming that directory we are reading is either has less than
- 100 files and so can be read in one initial chunk or has more than 1000
- files and so big increment are suitable.
- */
- #define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
- #define ENTRIES_INCREMENT (65536/sizeof(FILEINFO))
- #define NAMES_START_SIZE 32768
- static int comp_names(struct fileinfo *a,struct fileinfo *b);
- /* We need this because program don't know with malloc we used */
- void my_dirend(MY_DIR *buffer)
- {
- DBUG_ENTER("my_dirend");
- if (buffer)
- {
- delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer +
- ALIGN_SIZE(sizeof(MY_DIR))));
- free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
- my_free((gptr) buffer,MYF(0));
- }
- DBUG_VOID_RETURN;
- } /* my_dirend */
- /* Compare in sort of filenames */
- static int comp_names(struct fileinfo *a, struct fileinfo *b)
- {
- return (strcmp(a->name,b->name));
- } /* comp_names */
- #if !defined(MSDOS) && !defined(__WIN__)
- MY_DIR *my_dir(const char *path, myf MyFlags)
- {
- char *buffer;
- MY_DIR *result= 0;
- FILEINFO finfo;
- DYNAMIC_ARRAY *dir_entries_storage;
- MEM_ROOT *names_storage;
- DIR *dirp;
- struct dirent *dp;
- char tmp_path[FN_REFLEN+1],*tmp_file;
- #ifdef THREAD
- char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
- #endif
- DBUG_ENTER("my_dir");
- DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));
- #if defined(THREAD) && !defined(HAVE_READDIR_R)
- pthread_mutex_lock(&THR_LOCK_open);
- #endif
- dirp = opendir(directory_file_name(tmp_path,(my_string) path));
- #if defined(__amiga__)
- if ((dirp->dd_fd) < 0) /* Directory doesn't exists */
- goto error;
- #endif
- if (dirp == NULL ||
- ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
- sizeof(MEM_ROOT), MyFlags)))
- goto error;
- dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
- names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
-
- if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
- ENTRIES_START_SIZE, ENTRIES_INCREMENT))
- {
- my_free((gptr) buffer,MYF(0));
- goto error;
- }
- init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
-
- /* MY_DIR structure is allocated and completly initialized at this point */
- result= (MY_DIR*)buffer;
- tmp_file=strend(tmp_path);
- #ifdef THREAD
- dp= (struct dirent*) dirent_tmp;
- #else
- dp=0;
- #endif
-
- while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
- {
- if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
- goto error;
-
- if (MyFlags & MY_WANT_STAT)
- {
- if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
- sizeof(MY_STAT))))
- goto error;
-
- bzero(finfo.mystat, sizeof(MY_STAT));
- VOID(strmov(tmp_file,dp->d_name));
- VOID(my_stat(tmp_path, finfo.mystat, MyFlags));
- }
- else
- finfo.mystat= NULL;
- if (push_dynamic(dir_entries_storage, (gptr)&finfo))
- goto error;
- }
- (void) closedir(dirp);
- #if defined(THREAD) && !defined(HAVE_READDIR_R)
- pthread_mutex_unlock(&THR_LOCK_open);
- #endif
- result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
- result->number_off_files= dir_entries_storage->elements;
-
- if (!(MyFlags & MY_DONT_SORT))
- qsort((void *) result->dir_entry, result->number_off_files,
- sizeof(FILEINFO), (qsort_cmp) comp_names);
- DBUG_RETURN(result);
- error:
- #if defined(THREAD) && !defined(HAVE_READDIR_R)
- pthread_mutex_unlock(&THR_LOCK_open);
- #endif
- my_errno=errno;
- if (dirp)
- (void) closedir(dirp);
- my_dirend(result);
- if (MyFlags & (MY_FAE | MY_WME))
- my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
- DBUG_RETURN((MY_DIR *) NULL);
- } /* my_dir */
- /*
- * Convert from directory name to filename.
- * On VMS:
- * xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
- * xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
- * On UNIX, it's simple: just make sure there is a terminating /
- * Returns pointer to dst;
- */
- my_string directory_file_name (my_string dst, const char *src)
- {
- #ifndef VMS
- /* Process as Unix format: just remove test the final slash. */
- my_string end;
- if (src[0] == 0)
- src= (char*) "."; /* Use empty as current */
- end=strmov(dst, src);
- if (end[-1] != FN_LIBCHAR)
- {
- end[0]=FN_LIBCHAR; /* Add last '/' */
- end[1]=' ';
- }
- return dst;
- #else /* VMS */
- long slen;
- long rlen;
- my_string ptr, rptr;
- char bracket;
- struct FAB fab = cc$rms_fab;
- struct NAM nam = cc$rms_nam;
- char esa[NAM$C_MAXRSS];
- if (! src[0])
- src="[.]"; /* Empty is == current dir */
- slen = strlen (src) - 1;
- if (src[slen] == FN_C_AFTER_DIR || src[slen] == FN_C_AFTER_DIR_2 ||
- src[slen] == FN_DEVCHAR)
- {
- /* VMS style - convert [x.y.z] to [x.y]z, [x] to [000000]x */
- fab.fab$l_fna = src;
- fab.fab$b_fns = slen + 1;
- fab.fab$l_nam = &nam;
- fab.fab$l_fop = FAB$M_NAM;
- nam.nam$l_esa = esa;
- nam.nam$b_ess = sizeof esa;
- nam.nam$b_nop |= NAM$M_SYNCHK;
- /* We call SYS$PARSE to handle such things as [--] for us. */
- if (SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL)
- {
- slen = nam.nam$b_esl - 1;
- if (esa[slen] == ';' && esa[slen - 1] == '.')
- slen -= 2;
- esa[slen + 1] = ' ';
- src = esa;
- }
- if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2)
- {
- /* what about when we have logical_name:???? */
- if (src[slen] == FN_DEVCHAR)
- { /* Xlate logical name and see what we get */
- VOID(strmov(dst,src));
- dst[slen] = 0; /* remove colon */
- if (!(src = getenv (dst)))
- return dst; /* Can't translate */
- /* should we jump to the beginning of this procedure?
- Good points: allows us to use logical names that xlate
- to Unix names,
- Bad points: can be a problem if we just translated to a device
- name...
- For now, I'll punt and always expect VMS names, and hope for
- the best! */
- slen = strlen (src) - 1;
- if (src[slen] != FN_C_AFTER_DIR && src[slen] != FN_C_AFTER_DIR_2)
- { /* no recursion here! */
- VOID(strmov(dst, src));
- return(dst);
- }
- }
- else
- { /* not a directory spec */
- VOID(strmov(dst, src));
- return(dst);
- }
- }
- bracket = src[slen]; /* End char */
- if (!(ptr = strchr (src, bracket - 2)))
- { /* no opening bracket */
- VOID(strmov (dst, src));
- return dst;
- }
- if (!(rptr = strrchr (src, '.')))
- rptr = ptr;
- slen = rptr - src;
- VOID(strmake (dst, src, slen));
- if (*rptr == '.')
- { /* Put bracket and add */
- dst[slen++] = bracket; /* (rptr+1) after this */
- }
- else
- {
- /* If we have the top-level of a rooted directory (i.e. xx:[000000]),
- then translate the device and recurse. */
- if (dst[slen - 1] == ':'
- && dst[slen - 2] != ':' /* skip decnet nodes */
- && strcmp(src + slen, "[000000]") == 0)
- {
- dst[slen - 1] = ' ';
- if ((ptr = getenv (dst))
- && (rlen = strlen (ptr) - 1) > 0
- && (ptr[rlen] == FN_C_AFTER_DIR || ptr[rlen] == FN_C_AFTER_DIR_2)
- && ptr[rlen - 1] == '.')
- {
- VOID(strmov(esa,ptr));
- esa[rlen - 1] = FN_C_AFTER_DIR;
- esa[rlen] = ' ';
- return (directory_file_name (dst, esa));
- }
- else
- dst[slen - 1] = ':';
- }
- VOID(strmov(dst+slen,"[000000]"));
- slen += 8;
- }
- VOID(strmov(strmov(dst+slen,rptr+1)-1,".DIR.1"));
- return dst;
- }
- VOID(strmov(dst, src));
- if (dst[slen] == '/' && slen > 1)
- dst[slen] = 0;
- return dst;
- #endif /* VMS */
- } /* directory_file_name */
- #elif defined(WIN32)
- /*
- *****************************************************************************
- ** Read long filename using windows rutines
- *****************************************************************************
- */
- MY_DIR *my_dir(const char *path, myf MyFlags)
- {
- char *buffer;
- MY_DIR *result= 0;
- FILEINFO finfo;
- DYNAMIC_ARRAY *dir_entries_storage;
- MEM_ROOT *names_storage;
- #ifdef __BORLANDC__
- struct ffblk find;
- #else
- struct _finddata_t find;
- #endif
- ushort mode;
- char tmp_path[FN_REFLEN],*tmp_file,attrib;
- #ifdef _WIN64
- __int64 handle;
- #else
- long handle;
- #endif
- DBUG_ENTER("my_dir");
- DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags));
- /* Put LIB-CHAR as last path-character if not there */
- tmp_file=tmp_path;
- if (!*path)
- *tmp_file++ ='.'; /* From current dir */
- tmp_file= strmov(tmp_file,path);
- if (tmp_file[-1] == FN_DEVCHAR)
- *tmp_file++= '.'; /* From current dev-dir */
- if (tmp_file[-1] != FN_LIBCHAR)
- *tmp_file++ =FN_LIBCHAR;
- tmp_file[0]='*'; /* MSDOS needs this !??? */
- tmp_file[1]='.';
- tmp_file[2]='*';
- tmp_file[3]=' ';
- #ifdef __BORLANDC__
- if ((handle= findfirst(tmp_path,&find,0)) == -1L)
- goto error;
- #else
- if ((handle=_findfirst(tmp_path,&find)) == -1L)
- goto error;
- #endif
- if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
- sizeof(MEM_ROOT), MyFlags)))
- goto error;
- dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
- names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
-
- if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
- ENTRIES_START_SIZE, ENTRIES_INCREMENT))
- {
- my_free((gptr) buffer,MYF(0));
- goto error;
- }
- init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
-
- /* MY_DIR structure is allocated and completly initialized at this point */
- result= (MY_DIR*)buffer;
-
- do
- {
- #ifdef __BORLANDC__
- attrib= find.ff_attrib;
- #else
- attrib= find.attrib;
- /*
- Do not show hidden and system files which Windows sometimes create.
- Note. Because Borland's findfirst() is called with the third
- argument = 0 hidden/system files are excluded from the search.
- */
- if (attrib & (_A_HIDDEN | _A_SYSTEM))
- continue;
- #endif
- #ifdef __BORLANDC__
- if (!(finfo.name= strdup_root(names_storage, find.ff_name)))
- goto error;
- #else
- if (!(finfo.name= strdup_root(names_storage, find.name)))
- goto error;
- #endif
- if (MyFlags & MY_WANT_STAT)
- {
- if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
- sizeof(MY_STAT))))
- goto error;
-
- bzero(finfo.mystat, sizeof(MY_STAT));
- #ifdef __BORLANDC__
- finfo.mystat->st_size=find.ff_fsize;
- #else
- finfo.mystat->st_size=find.size;
- #endif
- mode=MY_S_IREAD;
- if (!(attrib & _A_RDONLY))
- mode|=MY_S_IWRITE;
- if (attrib & _A_SUBDIR)
- mode|=MY_S_IFDIR;
- finfo.mystat->st_mode=mode;
- #ifdef __BORLANDC__
- finfo.mystat->st_mtime=((uint32) find.ff_ftime);
- #else
- finfo.mystat->st_mtime=((uint32) find.time_write);
- #endif
- }
- else
- finfo.mystat= NULL;
- if (push_dynamic(dir_entries_storage, (gptr)&finfo))
- goto error;
-
- #ifdef __BORLANDC__
- } while (findnext(&find) == 0);
- #else
- } while (_findnext(handle,&find) == 0);
-
- _findclose(handle);
- #endif
- result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
- result->number_off_files= dir_entries_storage->elements;
-
- if (!(MyFlags & MY_DONT_SORT))
- qsort((void *) result->dir_entry, result->number_off_files,
- sizeof(FILEINFO), (qsort_cmp) comp_names);
- DBUG_RETURN(result);
- error:
- my_errno=errno;
- #ifndef __BORLANDC__
- if (handle != -1)
- _findclose(handle);
- #endif
- my_dirend(result);
- if (MyFlags & MY_FAE+MY_WME)
- my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
- DBUG_RETURN((MY_DIR *) NULL);
- } /* my_dir */
- #else /* MSDOS and not WIN32 */
- /******************************************************************************
- ** At MSDOS you always get stat of files, but time is in packed MSDOS-format
- ******************************************************************************/
- MY_DIR *my_dir(const char* path, myf MyFlags)
- {
- char *buffer;
- MY_DIR *result= 0;
- FILEINFO finfo;
- DYNAMIC_ARRAY *dir_entries_storage;
- MEM_ROOT *names_storage;
- struct find_t find;
- ushort mode;
- char tmp_path[FN_REFLEN],*tmp_file,attrib;
- DBUG_ENTER("my_dir");
- DBUG_PRINT("my",("path: '%s' stat: %d MyFlags: %d",path,MyFlags));
- /* Put LIB-CHAR as last path-character if not there */
- tmp_file=tmp_path;
- if (!*path)
- *tmp_file++ ='.'; /* From current dir */
- tmp_file= strmov(tmp_file,path);
- if (tmp_file[-1] == FN_DEVCHAR)
- *tmp_file++= '.'; /* From current dev-dir */
- if (tmp_file[-1] != FN_LIBCHAR)
- *tmp_file++ =FN_LIBCHAR;
- tmp_file[0]='*'; /* MSDOS needs this !??? */
- tmp_file[1]='.';
- tmp_file[2]='*';
- tmp_file[3]=' ';
- if (_dos_findfirst(tmp_path,_A_NORMAL | _A_SUBDIR, &find))
- goto error;
- if (!(buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
- sizeof(MEM_ROOT), MyFlags)))
- goto error;
- dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
- names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
- ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
-
- if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
- ENTRIES_START_SIZE, ENTRIES_INCREMENT))
- {
- my_free((gptr) buffer,MYF(0));
- goto error;
- }
- init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
-
- /* MY_DIR structure is allocated and completly initialized at this point */
- result= (MY_DIR*)buffer;
-
- do
- {
- if (!(finfo.name= strdup_root(names_storage, find.name)))
- goto error;
-
- if (MyFlags & MY_WANT_STAT)
- {
- if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage,
- sizeof(MY_STAT))))
- goto error;
-
- bzero(finfo.mystat, sizeof(MY_STAT));
- finfo.mystat->st_size= find.size;
- mode= MY_S_IREAD; attrib= find.attrib;
- if (!(attrib & _A_RDONLY))
- mode|= MY_S_IWRITE;
- if (attrib & _A_SUBDIR)
- mode|= MY_S_IFDIR;
- finfo.mystat->st_mode= mode;
- finfo.mystat->st_mtime= ((uint32) find.wr_date << 16) + find.wr_time;
- }
- else
- finfo.mystat= NULL;
- if (push_dynamic(dir_entries_storage, (gptr)&finfo))
- goto error;
-
- } while (_dos_findnext(&find) == 0);
-
- result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
- result->number_off_files= dir_entries_storage->elements;
-
- if (!(MyFlags & MY_DONT_SORT))
- qsort((void *) result->dir_entry, result->number_off_files,
- sizeof(FILEINFO), (qsort_cmp) comp_names);
- DBUG_RETURN(result);
- error:
- my_dirend(result);
- if (MyFlags & MY_FAE+MY_WME)
- my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
- DBUG_RETURN((MY_DIR *) NULL);
- } /* my_dir */
- #endif /* WIN32 && MSDOS */
- /****************************************************************************
- ** File status
- ** Note that MY_STAT is assumed to be same as struct stat
- ****************************************************************************/
- int my_fstat(int Filedes, MY_STAT *stat_area,
- myf MyFlags __attribute__((unused)))
- {
- DBUG_ENTER("my_fstat");
- DBUG_PRINT("my",("fd: %d MyFlags: %d",Filedes,MyFlags));
- DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area));
- }
- MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
- {
- int m_used;
- DBUG_ENTER("my_stat");
- DBUG_PRINT("my", ("path: '%s', stat_area: 0x%lx, MyFlags: %d", path,
- (byte *) stat_area, my_flags));
- if ((m_used= (stat_area == NULL)))
- if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
- goto error;
- if (! stat((my_string) path, (struct stat *) stat_area) )
- DBUG_RETURN(stat_area);
- DBUG_PRINT("error",("Got errno: %d from stat", errno));
- my_errno= errno;
- if (m_used) /* Free if new area */
- my_free((gptr) stat_area,MYF(0));
- error:
- if (my_flags & (MY_FAE+MY_WME))
- {
- my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),path,my_errno);
- DBUG_RETURN((MY_STAT *) NULL);
- }
- DBUG_RETURN((MY_STAT *) NULL);
- } /* my_stat */