~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"
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
20
#include	<mystrings/m_string.h>
1 by brian
clean slate
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
266.7.12 by Andy Lester
putting in proper const qualifiers
56
static int comp_names(const struct fileinfo *a, const struct fileinfo *b);
1 by brian
clean slate
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
  if (buffer)
64
  {
65
    delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer + 
66
                                    ALIGN_SIZE(sizeof(MY_DIR))));
67
    free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) + 
68
                          ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
69
    my_free((uchar*) buffer,MYF(0));
70
  }
51.3.13 by Jay Pipes
Phase 1 removal of DBUG in mysys
71
  return;
1 by brian
clean slate
72
} /* my_dirend */
73
74
75
	/* Compare in sort of filenames */
76
266.7.12 by Andy Lester
putting in proper const qualifiers
77
static int comp_names(const struct fileinfo *a, const struct fileinfo *b)
1 by brian
clean slate
78
{
79
  return (strcmp(a->name,b->name));
80
} /* comp_names */
81
82
83
MY_DIR	*my_dir(const char *path, myf MyFlags)
84
{
85
  char          *buffer;
86
  MY_DIR        *result= 0;
87
  FILEINFO      finfo;
88
  DYNAMIC_ARRAY *dir_entries_storage;
89
  MEM_ROOT      *names_storage;
90
  DIR		*dirp;
91
  struct dirent *dp;
92
  char		tmp_path[FN_REFLEN+1],*tmp_file;
93
  char	dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
94
28.1.35 by Monty Taylor
Removed all references to THREAD.
95
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
96
  pthread_mutex_lock(&THR_LOCK_open);
97
#endif
98
99
  dirp = opendir(directory_file_name(tmp_path,(char *) path));
100
  if (dirp == NULL || 
101
      ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + 
102
                           ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
103
                           sizeof(MEM_ROOT), MyFlags)))
104
    goto error;
105
106
  dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); 
107
  names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
108
                             ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
109
  
110
  if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
111
                            ENTRIES_START_SIZE, ENTRIES_INCREMENT))
112
  {
113
    my_free((uchar*) buffer,MYF(0));
114
    goto error;
115
  }
116
  init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
117
  
118
  /* MY_DIR structure is allocated and completly initialized at this point */
119
  result= (MY_DIR*)buffer;
120
121
  tmp_file=strend(tmp_path);
122
123
  dp= (struct dirent*) dirent_tmp;
124
  
125
  while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
126
  {
127
    if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
128
      goto error;
129
    
130
    if (MyFlags & MY_WANT_STAT)
131
    {
15 by brian
Fix for stat, NETWARE removal
132
      if (!(finfo.mystat= (struct stat*)alloc_root(names_storage, 
133
                                               sizeof(struct stat))))
1 by brian
clean slate
134
        goto error;
135
      
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
136
      memset(finfo.mystat, 0, sizeof(struct stat));
266.1.21 by Monty Taylor
Removed references to strmov and strnmov
137
      VOID(stpcpy(tmp_file,dp->d_name));
15 by brian
Fix for stat, NETWARE removal
138
      VOID(stat(tmp_path, finfo.mystat));
212.5.37 by Monty Taylor
Removed my_stat.
139
      if (!(finfo.mystat->st_mode & S_IREAD))
1 by brian
clean slate
140
        continue;
141
    }
142
    else
143
      finfo.mystat= NULL;
144
145
    if (push_dynamic(dir_entries_storage, (uchar*)&finfo))
146
      goto error;
147
  }
148
149
  (void) closedir(dirp);
28.1.35 by Monty Taylor
Removed all references to THREAD.
150
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
151
  pthread_mutex_unlock(&THR_LOCK_open);
152
#endif
153
  result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
154
  result->number_off_files= dir_entries_storage->elements;
155
  
156
  if (!(MyFlags & MY_DONT_SORT))
157
    my_qsort((void *) result->dir_entry, result->number_off_files,
158
          sizeof(FILEINFO), (qsort_cmp) comp_names);
51.3.13 by Jay Pipes
Phase 1 removal of DBUG in mysys
159
  return(result);
1 by brian
clean slate
160
161
 error:
28.1.35 by Monty Taylor
Removed all references to THREAD.
162
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
163
  pthread_mutex_unlock(&THR_LOCK_open);
164
#endif
165
  my_errno=errno;
166
  if (dirp)
167
    (void) closedir(dirp);
168
  my_dirend(result);
169
  if (MyFlags & (MY_FAE | MY_WME))
170
    my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
51.3.13 by Jay Pipes
Phase 1 removal of DBUG in mysys
171
  return((MY_DIR *) NULL);
1 by brian
clean slate
172
} /* my_dir */
173
174
175
/*
176
 * Convert from directory name to filename.
177
 * On VMS:
178
 *	 xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
179
 *	 xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
180
 * On UNIX, it's simple: just make sure there is a terminating /
181
182
 * Returns pointer to dst;
183
 */
184
185
char * directory_file_name (char * dst, const char *src)
186
{
187
  /* Process as Unix format: just remove test the final slash. */
188
189
  char * end;
190
191
  if (src[0] == 0)
192
    src= (char*) ".";				/* Use empty as current */
266.1.21 by Monty Taylor
Removed references to strmov and strnmov
193
  end=stpcpy(dst, src);
1 by brian
clean slate
194
  if (end[-1] != FN_LIBCHAR)
195
  {
196
    end[0]=FN_LIBCHAR;				/* Add last '/' */
197
    end[1]='\0';
198
  }
199
  return dst;
200
} /* directory_file_name */
201