1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
/* TODO: check for overun of memory for names. */
17
/* Convert MSDOS-TIME to standar time_t (still needed?) */
19
#include "mysys_priv.h"
20
#include <mystrings/m_string.h>
21
#include <my_dir.h> /* Structs used by my_dir,includes sys/types */
22
#include "mysys_err.h"
23
#if defined(HAVE_DIRENT_H)
26
# define dirent direct
27
# if defined(HAVE_SYS_NDIR_H)
28
# include <sys/ndir.h>
30
# if defined(HAVE_SYS_DIR_H)
33
# if defined(HAVE_NDIR_H)
38
#if defined(HAVE_READDIR_R)
39
#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
41
#define READDIR(A,B,C) (!(C=readdir(A)))
45
We are assuming that directory we are reading is either has less than
46
100 files and so can be read in one initial chunk or has more than 1000
47
files and so big increment are suitable.
49
#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
50
#define ENTRIES_INCREMENT (65536/sizeof(FILEINFO))
51
#define NAMES_START_SIZE 32768
54
static int comp_names(const struct fileinfo *a, const struct fileinfo *b);
57
/* We need this because program don't know with malloc we used */
59
void my_dirend(MY_DIR *buffer)
63
delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer +
64
ALIGN_SIZE(sizeof(MY_DIR))));
65
free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
66
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
67
free((unsigned char*) buffer);
73
/* Compare in sort of filenames */
75
static int comp_names(const struct fileinfo *a, const struct fileinfo *b)
77
return (strcmp(a->name,b->name));
81
MY_DIR *my_dir(const char *path, myf MyFlags)
86
DYNAMIC_ARRAY *dir_entries_storage;
87
MEM_ROOT *names_storage;
90
char tmp_path[FN_REFLEN+1],*tmp_file;
91
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
93
#if !defined(HAVE_READDIR_R)
94
pthread_mutex_lock(&THR_LOCK_open);
97
dirp = opendir(directory_file_name(tmp_path,(char *) path));
99
! (buffer= (char *) malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
100
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
104
dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
105
names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
106
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
108
if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
109
ENTRIES_START_SIZE, ENTRIES_INCREMENT))
111
free((unsigned char*) buffer);
114
init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
116
/* MY_DIR structure is allocated and completly initialized at this point */
117
result= (MY_DIR*)buffer;
119
tmp_file= strchr(tmp_path, '\0');
121
dp= (struct dirent*) dirent_tmp;
123
while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
125
if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
128
if (MyFlags & MY_WANT_STAT)
130
if (!(finfo.mystat= (struct stat*)alloc_root(names_storage,
131
sizeof(struct stat))))
134
memset(finfo.mystat, 0, sizeof(struct stat));
135
strcpy(tmp_file,dp->d_name);
136
stat(tmp_path, finfo.mystat);
137
if (!(finfo.mystat->st_mode & S_IREAD))
143
if (push_dynamic(dir_entries_storage, (unsigned char*)&finfo))
147
(void) closedir(dirp);
148
#if !defined(HAVE_READDIR_R)
149
pthread_mutex_unlock(&THR_LOCK_open);
151
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
152
result->number_off_files= dir_entries_storage->elements;
154
if (!(MyFlags & MY_DONT_SORT))
155
my_qsort((void *) result->dir_entry, result->number_off_files,
156
sizeof(FILEINFO), (qsort_cmp) comp_names);
160
#if !defined(HAVE_READDIR_R)
161
pthread_mutex_unlock(&THR_LOCK_open);
165
(void) closedir(dirp);
167
if (MyFlags & (MY_FAE | MY_WME))
168
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
169
return((MY_DIR *) NULL);
174
* Convert from directory name to filename.
176
* xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
177
* xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
178
* On UNIX, it's simple: just make sure there is a terminating /
180
* Returns pointer to dst;
183
char * directory_file_name (char * dst, const char *src)
185
/* Process as Unix format: just remove test the final slash. */
190
src= (char*) "."; /* Use empty as current */
191
end= strcpy(dst, src)+strlen(src);
192
if (end[-1] != FN_LIBCHAR)
194
end[0]=FN_LIBCHAR; /* Add last '/' */
198
} /* directory_file_name */