~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
#else
26
# define dirent direct
27
# if defined(HAVE_SYS_NDIR_H)
28
#  include <sys/ndir.h>
29
# endif
30
# if defined(HAVE_SYS_DIR_H)
31
#  include <sys/dir.h>
32
# endif
33
# if defined(HAVE_NDIR_H)
34
#  include <ndir.h>
35
# endif
36
#endif
37
28.1.35 by Monty Taylor
Removed all references to THREAD.
38
#if defined(HAVE_READDIR_R)
1 by brian
clean slate
39
#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
40
#else
41
#define READDIR(A,B,C) (!(C=readdir(A)))
42
#endif
43
44
/*
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.
48
*/
49
#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
50
#define ENTRIES_INCREMENT  (65536/sizeof(FILEINFO))
51
#define NAMES_START_SIZE   32768
52
53
266.7.12 by Andy Lester
putting in proper const qualifiers
54
static int comp_names(const struct fileinfo *a, const struct fileinfo *b);
1 by brian
clean slate
55
56
57
	/* We need this because program don't know with malloc we used */
58
59
void my_dirend(MY_DIR *buffer)
60
{
61
  if (buffer)
62
  {
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));
481 by Brian Aker
Remove all of uchar.
67
    free((unsigned char*) buffer);
1 by brian
clean slate
68
  }
51.3.13 by Jay Pipes
Phase 1 removal of DBUG in mysys
69
  return;
1 by brian
clean slate
70
} /* my_dirend */
71
72
73
	/* Compare in sort of filenames */
74
266.7.12 by Andy Lester
putting in proper const qualifiers
75
static int comp_names(const struct fileinfo *a, const struct fileinfo *b)
1 by brian
clean slate
76
{
77
  return (strcmp(a->name,b->name));
78
} /* comp_names */
79
80
81
MY_DIR	*my_dir(const char *path, myf MyFlags)
82
{
83
  char          *buffer;
84
  MY_DIR        *result= 0;
85
  FILEINFO      finfo;
86
  DYNAMIC_ARRAY *dir_entries_storage;
87
  MEM_ROOT      *names_storage;
88
  DIR		*dirp;
89
  struct dirent *dp;
90
  char		tmp_path[FN_REFLEN+1],*tmp_file;
91
  char	dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
92
28.1.35 by Monty Taylor
Removed all references to THREAD.
93
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
94
  pthread_mutex_lock(&THR_LOCK_open);
95
#endif
96
97
  dirp = opendir(directory_file_name(tmp_path,(char *) path));
98
  if (dirp == NULL || 
99
      ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + 
100
                           ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
101
                           sizeof(MEM_ROOT), MyFlags)))
102
    goto error;
103
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)));
107
  
108
  if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
109
                            ENTRIES_START_SIZE, ENTRIES_INCREMENT))
110
  {
481 by Brian Aker
Remove all of uchar.
111
    free((unsigned char*) buffer);
1 by brian
clean slate
112
    goto error;
113
  }
114
  init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
115
  
116
  /* MY_DIR structure is allocated and completly initialized at this point */
117
  result= (MY_DIR*)buffer;
118
376 by Brian Aker
strend remove
119
  tmp_file= strchr(tmp_path, '\0');
1 by brian
clean slate
120
121
  dp= (struct dirent*) dirent_tmp;
122
  
123
  while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
124
  {
125
    if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
126
      goto error;
127
    
128
    if (MyFlags & MY_WANT_STAT)
129
    {
15 by brian
Fix for stat, NETWARE removal
130
      if (!(finfo.mystat= (struct stat*)alloc_root(names_storage, 
131
                                               sizeof(struct stat))))
1 by brian
clean slate
132
        goto error;
133
      
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
134
      memset(finfo.mystat, 0, sizeof(struct stat));
419 by Monty
Merged up to 408 of stdint-includes-fix.
135
      my_stpcpy(tmp_file,dp->d_name);
398.1.10 by Monty Taylor
Actually removed VOID() this time.
136
      stat(tmp_path, finfo.mystat);
212.5.37 by Monty Taylor
Removed my_stat.
137
      if (!(finfo.mystat->st_mode & S_IREAD))
1 by brian
clean slate
138
        continue;
139
    }
140
    else
141
      finfo.mystat= NULL;
142
481 by Brian Aker
Remove all of uchar.
143
    if (push_dynamic(dir_entries_storage, (unsigned char*)&finfo))
1 by brian
clean slate
144
      goto error;
145
  }
146
147
  (void) closedir(dirp);
28.1.35 by Monty Taylor
Removed all references to THREAD.
148
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
149
  pthread_mutex_unlock(&THR_LOCK_open);
150
#endif
151
  result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
152
  result->number_off_files= dir_entries_storage->elements;
153
  
154
  if (!(MyFlags & MY_DONT_SORT))
155
    my_qsort((void *) result->dir_entry, result->number_off_files,
156
          sizeof(FILEINFO), (qsort_cmp) comp_names);
51.3.13 by Jay Pipes
Phase 1 removal of DBUG in mysys
157
  return(result);
1 by brian
clean slate
158
159
 error:
28.1.35 by Monty Taylor
Removed all references to THREAD.
160
#if !defined(HAVE_READDIR_R)
1 by brian
clean slate
161
  pthread_mutex_unlock(&THR_LOCK_open);
162
#endif
163
  my_errno=errno;
164
  if (dirp)
165
    (void) closedir(dirp);
166
  my_dirend(result);
167
  if (MyFlags & (MY_FAE | MY_WME))
168
    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
169
  return((MY_DIR *) NULL);
1 by brian
clean slate
170
} /* my_dir */
171
172
173
/*
174
 * Convert from directory name to filename.
175
 * On VMS:
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 /
179
180
 * Returns pointer to dst;
181
 */
182
183
char * directory_file_name (char * dst, const char *src)
184
{
185
  /* Process as Unix format: just remove test the final slash. */
186
187
  char * end;
188
189
  if (src[0] == 0)
190
    src= (char*) ".";				/* Use empty as current */
411.1.1 by Brian Aker
Work on removing GNU specific calls.
191
  end=my_stpcpy(dst, src);
1 by brian
clean slate
192
  if (end[-1] != FN_LIBCHAR)
193
  {
194
    end[0]=FN_LIBCHAR;				/* Add last '/' */
195
    end[1]='\0';
196
  }
197
  return dst;
198
} /* directory_file_name */
199