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. */
20
#include "drizzled/internal/mysys_priv.h"
21
#include "drizzled/internal/m_string.h"
22
#include "drizzled/my_error.h"
23
#include "drizzled/internal/my_dir.h" /* Structs used by my_dir,includes sys/types */
25
using namespace drizzled;
27
#if defined(HAVE_READDIR_R)
28
#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
30
#error You must have a thread safe readdir()
34
We are assuming that directory we are reading is either has less than
35
100 files and so can be read in one initial chunk or has more than 1000
36
files and so big increment are suitable.
38
#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
39
#define ENTRIES_INCREMENT (65536/sizeof(FILEINFO))
40
#define NAMES_START_SIZE 32768
43
static int comp_names(const struct fileinfo *a, const struct fileinfo *b);
44
static char* directory_file_name(char* dst, const char* src);
46
/* We need this because program don't know with malloc we used */
48
void my_dirend(MY_DIR *buffer)
52
delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer +
53
ALIGN_SIZE(sizeof(MY_DIR))));
54
free_root((memory::Root*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
55
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
56
free((unsigned char*) buffer);
62
/* Compare in sort of filenames */
64
static int comp_names(const struct fileinfo *a, const struct fileinfo *b)
66
return (strcmp(a->name,b->name));
70
MY_DIR *my_dir(const char *path, myf MyFlags)
75
DYNAMIC_ARRAY *dir_entries_storage;
76
memory::Root *names_storage;
79
char tmp_path[FN_REFLEN+1],*tmp_file;
80
char dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
82
dirp = opendir(directory_file_name(tmp_path,(char *) path));
84
! (buffer= (char *) malloc(ALIGN_SIZE(sizeof(MY_DIR)) +
85
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
86
sizeof(memory::Root))))
89
dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
90
names_storage= (memory::Root*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
91
ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
93
if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
94
ENTRIES_START_SIZE, ENTRIES_INCREMENT))
96
free((unsigned char*) buffer);
99
init_alloc_root(names_storage, NAMES_START_SIZE);
101
/* MY_DIR structure is allocated and completly initialized at this point */
102
result= (MY_DIR*)buffer;
104
tmp_file= strchr(tmp_path, '\0');
106
dp= (struct dirent*) dirent_tmp;
108
while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
110
if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
113
if (MyFlags & MY_WANT_STAT)
115
if (!(finfo.mystat= (struct stat*)alloc_root(names_storage,
116
sizeof(struct stat))))
119
memset(finfo.mystat, 0, sizeof(struct stat));
120
strcpy(tmp_file,dp->d_name);
121
stat(tmp_path, finfo.mystat);
122
if (!(finfo.mystat->st_mode & S_IREAD))
128
if (push_dynamic(dir_entries_storage, (unsigned char*)&finfo))
132
(void) closedir(dirp);
134
result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
135
result->number_off_files= static_cast<uint>(dir_entries_storage->elements);
137
if (!(MyFlags & MY_DONT_SORT))
138
my_qsort((void *) result->dir_entry, result->number_off_files,
139
sizeof(FILEINFO), (qsort_cmp) comp_names);
146
(void) closedir(dirp);
148
if (MyFlags & (MY_FAE | MY_WME))
149
my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,errno);
151
return((MY_DIR *) NULL);
156
* Convert from directory name to filename.
158
* xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
159
* xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
160
* On UNIX, it's simple: just make sure there is a terminating /
162
* Returns pointer to dst;
165
static char* directory_file_name(char* dst, const char* src)
167
/* Process as Unix format: just remove test the final slash. */
172
src= (char*) "."; /* Use empty as current */
173
end= strcpy(dst, src)+strlen(src);
174
if (end[-1] != FN_LIBCHAR)
176
end[0]=FN_LIBCHAR; /* Add last '/' */
180
} /* directory_file_name */