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"
21
#include <my_dir.h> /* Structs used by my_dir,includes sys/types */
22
#include "mysys_err.h"
23
#if defined(HAVE_DIRENT_H)
25
# define NAMLEN(dirent) strlen((dirent)->d_name)
27
# define dirent direct
28
# define NAMLEN(dirent) (dirent)->d_namlen
29
# if defined(HAVE_SYS_NDIR_H)
30
# include <sys/ndir.h>
32
# if defined(HAVE_SYS_DIR_H)
35
# if defined(HAVE_NDIR_H)
40
#if defined(HAVE_READDIR_R)
41
#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
43
#define READDIR(A,B,C) (!(C=readdir(A)))
47
We are assuming that directory we are reading is either has less than
48
100 files and so can be read in one initial chunk or has more than 1000
49
files and so big increment are suitable.
51
#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
52
#define ENTRIES_INCREMENT (65536/sizeof(FILEINFO))
53
#define NAMES_START_SIZE 32768
56
static int comp_names(struct fileinfo *a,struct fileinfo *b);
59
/* We need this because program don't know with malloc we used */
61
void my_dirend(MY_DIR *buffer)
63
DBUG_ENTER("my_dirend");
66
delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer +
67
ALIGN_SIZE(sizeof(MY_DIR))));
68
free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
69
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
70
my_free((uchar*) buffer,MYF(0));
76
/* Compare in sort of filenames */
78
static int comp_names(struct fileinfo *a, struct fileinfo *b)
80
return (strcmp(a->name,b->name));
84
MY_DIR *my_dir(const char *path, myf MyFlags)
89
DYNAMIC_ARRAY *dir_entries_storage;
90
MEM_ROOT *names_storage;
93
char tmp_path[FN_REFLEN+1],*tmp_file;
94
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
96
DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));
98
#if !defined(HAVE_READDIR_R)
99
pthread_mutex_lock(&THR_LOCK_open);
102
dirp = opendir(directory_file_name(tmp_path,(char *) path));
104
! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
105
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
106
sizeof(MEM_ROOT), MyFlags)))
109
dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
110
names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
111
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
113
if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
114
ENTRIES_START_SIZE, ENTRIES_INCREMENT))
116
my_free((uchar*) buffer,MYF(0));
119
init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
121
/* MY_DIR structure is allocated and completly initialized at this point */
122
result= (MY_DIR*)buffer;
124
tmp_file=strend(tmp_path);
126
dp= (struct dirent*) dirent_tmp;
128
while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
130
if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
133
if (MyFlags & MY_WANT_STAT)
135
if (!(finfo.mystat= (struct stat*)alloc_root(names_storage,
136
sizeof(struct stat))))
139
bzero(finfo.mystat, sizeof(struct stat));
140
VOID(strmov(tmp_file,dp->d_name));
141
VOID(stat(tmp_path, finfo.mystat));
142
if (!(finfo.mystat->st_mode & MY_S_IREAD))
148
if (push_dynamic(dir_entries_storage, (uchar*)&finfo))
152
(void) closedir(dirp);
153
#if !defined(HAVE_READDIR_R)
154
pthread_mutex_unlock(&THR_LOCK_open);
156
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
157
result->number_off_files= dir_entries_storage->elements;
159
if (!(MyFlags & MY_DONT_SORT))
160
my_qsort((void *) result->dir_entry, result->number_off_files,
161
sizeof(FILEINFO), (qsort_cmp) comp_names);
165
#if !defined(HAVE_READDIR_R)
166
pthread_mutex_unlock(&THR_LOCK_open);
170
(void) closedir(dirp);
172
if (MyFlags & (MY_FAE | MY_WME))
173
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
174
DBUG_RETURN((MY_DIR *) NULL);
179
* Convert from directory name to filename.
181
* xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
182
* xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
183
* On UNIX, it's simple: just make sure there is a terminating /
185
* Returns pointer to dst;
188
char * directory_file_name (char * dst, const char *src)
190
/* Process as Unix format: just remove test the final slash. */
195
src= (char*) "."; /* Use empty as current */
196
end=strmov(dst, src);
197
if (end[-1] != FN_LIBCHAR)
199
end[0]=FN_LIBCHAR; /* Add last '/' */
203
} /* directory_file_name */