~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
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.
6
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.
11
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 */
15
16
/* TODO: check for overun of memory for names. */
17
/*	 Convert MSDOS-TIME to standar time_t (still needed?) */
18
19
#include	"mysys_priv.h"
20
#include	<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)
24
# include <dirent.h>
25
# define NAMLEN(dirent) strlen((dirent)->d_name)
26
#else
27
# define dirent direct
28
# define NAMLEN(dirent) (dirent)->d_namlen
29
# if defined(HAVE_SYS_NDIR_H)
30
#  include <sys/ndir.h>
31
# endif
32
# if defined(HAVE_SYS_DIR_H)
33
#  include <sys/dir.h>
34
# endif
35
# if defined(HAVE_NDIR_H)
36
#  include <ndir.h>
37
# endif
38
#endif
39
28.1.35 by Monty Taylor
Removed all references to THREAD.
40
#if defined(HAVE_READDIR_R)
1 by brian
clean slate
41
#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
42
#else
43
#define READDIR(A,B,C) (!(C=readdir(A)))
44
#endif
45
46
/*
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.
50
*/
51
#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
52
#define ENTRIES_INCREMENT  (65536/sizeof(FILEINFO))
53
#define NAMES_START_SIZE   32768
54
55
56
static int	comp_names(struct fileinfo *a,struct fileinfo *b);
57
58
59
	/* We need this because program don't know with malloc we used */
60
61
void my_dirend(MY_DIR *buffer)
62
{
63
  DBUG_ENTER("my_dirend");
64
  if (buffer)
65
  {
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));
71
  }
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
MY_DIR	*my_dir(const char *path, myf MyFlags)
85
{
86
  char          *buffer;
87
  MY_DIR        *result= 0;
88
  FILEINFO      finfo;
89
  DYNAMIC_ARRAY *dir_entries_storage;
90
  MEM_ROOT      *names_storage;
91
  DIR		*dirp;
92
  struct dirent *dp;
93
  char		tmp_path[FN_REFLEN+1],*tmp_file;
94
  char	dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
95
  DBUG_ENTER("my_dir");
96
  DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));
97
28.1.35 by Monty Taylor
Removed all references to THREAD.
98
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
99
  pthread_mutex_lock(&THR_LOCK_open);
100
#endif
101
102
  dirp = opendir(directory_file_name(tmp_path,(char *) path));
103
  if (dirp == NULL || 
104
      ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + 
105
                           ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
106
                           sizeof(MEM_ROOT), MyFlags)))
107
    goto error;
108
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)));
112
  
113
  if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
114
                            ENTRIES_START_SIZE, ENTRIES_INCREMENT))
115
  {
116
    my_free((uchar*) buffer,MYF(0));
117
    goto error;
118
  }
119
  init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
120
  
121
  /* MY_DIR structure is allocated and completly initialized at this point */
122
  result= (MY_DIR*)buffer;
123
124
  tmp_file=strend(tmp_path);
125
126
  dp= (struct dirent*) dirent_tmp;
127
  
128
  while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
129
  {
130
    if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
131
      goto error;
132
    
133
    if (MyFlags & MY_WANT_STAT)
134
    {
15 by brian
Fix for stat, NETWARE removal
135
      if (!(finfo.mystat= (struct stat*)alloc_root(names_storage, 
136
                                               sizeof(struct stat))))
1 by brian
clean slate
137
        goto error;
138
      
15 by brian
Fix for stat, NETWARE removal
139
      bzero(finfo.mystat, sizeof(struct stat));
1 by brian
clean slate
140
      VOID(strmov(tmp_file,dp->d_name));
15 by brian
Fix for stat, NETWARE removal
141
      VOID(stat(tmp_path, finfo.mystat));
1 by brian
clean slate
142
      if (!(finfo.mystat->st_mode & MY_S_IREAD))
143
        continue;
144
    }
145
    else
146
      finfo.mystat= NULL;
147
148
    if (push_dynamic(dir_entries_storage, (uchar*)&finfo))
149
      goto error;
150
  }
151
152
  (void) closedir(dirp);
28.1.35 by Monty Taylor
Removed all references to THREAD.
153
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
154
  pthread_mutex_unlock(&THR_LOCK_open);
155
#endif
156
  result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
157
  result->number_off_files= dir_entries_storage->elements;
158
  
159
  if (!(MyFlags & MY_DONT_SORT))
160
    my_qsort((void *) result->dir_entry, result->number_off_files,
161
          sizeof(FILEINFO), (qsort_cmp) comp_names);
162
  DBUG_RETURN(result);
163
164
 error:
28.1.35 by Monty Taylor
Removed all references to THREAD.
165
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
166
  pthread_mutex_unlock(&THR_LOCK_open);
167
#endif
168
  my_errno=errno;
169
  if (dirp)
170
    (void) closedir(dirp);
171
  my_dirend(result);
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);
175
} /* my_dir */
176
177
178
/*
179
 * Convert from directory name to filename.
180
 * On VMS:
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 /
184
185
 * Returns pointer to dst;
186
 */
187
188
char * directory_file_name (char * dst, const char *src)
189
{
190
  /* Process as Unix format: just remove test the final slash. */
191
192
  char * end;
193
194
  if (src[0] == 0)
195
    src= (char*) ".";				/* Use empty as current */
196
  end=strmov(dst, src);
197
  if (end[-1] != FN_LIBCHAR)
198
  {
199
    end[0]=FN_LIBCHAR;				/* Add last '/' */
200
    end[1]='\0';
201
  }
202
  return dst;
203
} /* directory_file_name */
204