~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_lib.c

Cleanup around SAFEMALLOC

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        <mystrings/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(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(const struct fileinfo *a, const 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
  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
  }
 
71
  return;
 
72
} /* my_dirend */
 
73
 
 
74
 
 
75
        /* Compare in sort of filenames */
 
76
 
 
77
static int comp_names(const struct fileinfo *a, const struct fileinfo *b)
 
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
 
 
95
#if !defined(HAVE_READDIR_R)
 
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= strchr(tmp_path, '\0');
 
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
    {
 
132
      if (!(finfo.mystat= (struct stat*)alloc_root(names_storage, 
 
133
                                               sizeof(struct stat))))
 
134
        goto error;
 
135
      
 
136
      memset(finfo.mystat, 0, sizeof(struct stat));
 
137
      VOID(stpcpy(tmp_file,dp->d_name));
 
138
      VOID(stat(tmp_path, finfo.mystat));
 
139
      if (!(finfo.mystat->st_mode & S_IREAD))
 
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);
 
150
#if !defined(HAVE_READDIR_R)
 
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);
 
159
  return(result);
 
160
 
 
161
 error:
 
162
#if !defined(HAVE_READDIR_R)
 
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);
 
171
  return((MY_DIR *) NULL);
 
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 */
 
193
  end=stpcpy(dst, src);
 
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