~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to mysys/my_lib.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
40
#if defined(THREAD) && defined(HAVE_READDIR_R)
 
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
#ifdef THREAD
 
95
  char  dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
 
96
#endif
 
97
  DBUG_ENTER("my_dir");
 
98
  DBUG_PRINT("my",("path: '%s' MyFlags: %d",path,MyFlags));
 
99
 
 
100
#if defined(THREAD) && !defined(HAVE_READDIR_R)
 
101
  pthread_mutex_lock(&THR_LOCK_open);
 
102
#endif
 
103
 
 
104
  dirp = opendir(directory_file_name(tmp_path,(char *) path));
 
105
  if (dirp == NULL || 
 
106
      ! (buffer= my_malloc(ALIGN_SIZE(sizeof(MY_DIR)) + 
 
107
                           ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
 
108
                           sizeof(MEM_ROOT), MyFlags)))
 
109
    goto error;
 
110
 
 
111
  dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR))); 
 
112
  names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
 
113
                             ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
 
114
  
 
115
  if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
 
116
                            ENTRIES_START_SIZE, ENTRIES_INCREMENT))
 
117
  {
 
118
    my_free((uchar*) buffer,MYF(0));
 
119
    goto error;
 
120
  }
 
121
  init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
 
122
  
 
123
  /* MY_DIR structure is allocated and completly initialized at this point */
 
124
  result= (MY_DIR*)buffer;
 
125
 
 
126
  tmp_file=strend(tmp_path);
 
127
 
 
128
#ifdef THREAD
 
129
  dp= (struct dirent*) dirent_tmp;
 
130
#else
 
131
  dp=0;
 
132
#endif
 
133
  
 
134
  while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
 
135
  {
 
136
    if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
 
137
      goto error;
 
138
    
 
139
    if (MyFlags & MY_WANT_STAT)
 
140
    {
 
141
      if (!(finfo.mystat= (MY_STAT*)alloc_root(names_storage, 
 
142
                                               sizeof(MY_STAT))))
 
143
        goto error;
 
144
      
 
145
      bzero(finfo.mystat, sizeof(MY_STAT));
 
146
      VOID(strmov(tmp_file,dp->d_name));
 
147
      VOID(my_stat(tmp_path, finfo.mystat, MyFlags));
 
148
      if (!(finfo.mystat->st_mode & MY_S_IREAD))
 
149
        continue;
 
150
    }
 
151
    else
 
152
      finfo.mystat= NULL;
 
153
 
 
154
    if (push_dynamic(dir_entries_storage, (uchar*)&finfo))
 
155
      goto error;
 
156
  }
 
157
 
 
158
  (void) closedir(dirp);
 
159
#if defined(THREAD) && !defined(HAVE_READDIR_R)
 
160
  pthread_mutex_unlock(&THR_LOCK_open);
 
161
#endif
 
162
  result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
 
163
  result->number_off_files= dir_entries_storage->elements;
 
164
  
 
165
  if (!(MyFlags & MY_DONT_SORT))
 
166
    my_qsort((void *) result->dir_entry, result->number_off_files,
 
167
          sizeof(FILEINFO), (qsort_cmp) comp_names);
 
168
  DBUG_RETURN(result);
 
169
 
 
170
 error:
 
171
#if defined(THREAD) && !defined(HAVE_READDIR_R)
 
172
  pthread_mutex_unlock(&THR_LOCK_open);
 
173
#endif
 
174
  my_errno=errno;
 
175
  if (dirp)
 
176
    (void) closedir(dirp);
 
177
  my_dirend(result);
 
178
  if (MyFlags & (MY_FAE | MY_WME))
 
179
    my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
 
180
  DBUG_RETURN((MY_DIR *) NULL);
 
181
} /* my_dir */
 
182
 
 
183
 
 
184
/*
 
185
 * Convert from directory name to filename.
 
186
 * On VMS:
 
187
 *       xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
 
188
 *       xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
 
189
 * On UNIX, it's simple: just make sure there is a terminating /
 
190
 
 
191
 * Returns pointer to dst;
 
192
 */
 
193
 
 
194
char * directory_file_name (char * dst, const char *src)
 
195
{
 
196
  /* Process as Unix format: just remove test the final slash. */
 
197
 
 
198
  char * end;
 
199
 
 
200
  if (src[0] == 0)
 
201
    src= (char*) ".";                           /* Use empty as current */
 
202
  end=strmov(dst, src);
 
203
  if (end[-1] != FN_LIBCHAR)
 
204
  {
 
205
    end[0]=FN_LIBCHAR;                          /* Add last '/' */
 
206
    end[1]='\0';
 
207
  }
 
208
  return dst;
 
209
} /* directory_file_name */
 
210
 
 
211
 
 
212
/****************************************************************************
 
213
** File status
 
214
** Note that MY_STAT is assumed to be same as struct stat
 
215
****************************************************************************/ 
 
216
 
 
217
int my_fstat(int Filedes, MY_STAT *stat_area,
 
218
             myf MyFlags __attribute__((unused)))
 
219
{
 
220
  DBUG_ENTER("my_fstat");
 
221
  DBUG_PRINT("my",("fd: %d  MyFlags: %d", Filedes, MyFlags));
 
222
  DBUG_RETURN(fstat(Filedes, (struct stat *) stat_area));
 
223
}
 
224
 
 
225
 
 
226
MY_STAT *my_stat(const char *path, MY_STAT *stat_area, myf my_flags)
 
227
{
 
228
  int m_used;
 
229
  DBUG_ENTER("my_stat");
 
230
  DBUG_PRINT("my", ("path: '%s'  stat_area: 0x%lx  MyFlags: %d", path,
 
231
                    (long) stat_area, my_flags));
 
232
 
 
233
  if ((m_used= (stat_area == NULL)))
 
234
    if (!(stat_area = (MY_STAT *) my_malloc(sizeof(MY_STAT), my_flags)))
 
235
      goto error;
 
236
  if (! stat((char *) path, (struct stat *) stat_area) )
 
237
    DBUG_RETURN(stat_area);
 
238
 
 
239
  DBUG_PRINT("error",("Got errno: %d from stat", errno));
 
240
  my_errno= errno;
 
241
  if (m_used)                                   /* Free if new area */
 
242
    my_free((uchar*) stat_area,MYF(0));
 
243
 
 
244
error:
 
245
  if (my_flags & (MY_FAE+MY_WME))
 
246
  {
 
247
    my_error(EE_STAT, MYF(ME_BELL+ME_WAITTANG),path,my_errno);
 
248
    DBUG_RETURN((MY_STAT *) NULL);
 
249
  }
 
250
  DBUG_RETURN((MY_STAT *) NULL);
 
251
} /* my_stat */