~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_lib.cc

Reverted my change to interval_list

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
 
 
18
#include        "mysys/mysys_priv.h"
 
19
#include        <mystrings/m_string.h>
 
20
#include        "mysys/mysys_err.h"
 
21
#include        "my_dir.h"      /* Structs used by my_dir,includes sys/types */
 
22
#if defined(HAVE_DIRENT_H)
 
23
# include <dirent.h>
 
24
#else
 
25
# define dirent direct
 
26
# if defined(HAVE_SYS_NDIR_H)
 
27
#  include <sys/ndir.h>
 
28
# endif
 
29
# if defined(HAVE_SYS_DIR_H)
 
30
#  include <sys/dir.h>
 
31
# endif
 
32
# if defined(HAVE_NDIR_H)
 
33
#  include <ndir.h>
 
34
# endif
 
35
#endif
 
36
 
 
37
#if defined(HAVE_READDIR_R)
 
38
#define READDIR(A,B,C) ((errno=readdir_r(A,B,&C)) != 0 || !C)
 
39
#else 
 
40
#error You must have a thread safe readdir() 
 
41
#endif
 
42
 
 
43
/*
 
44
  We are assuming that directory we are reading is either has less than
 
45
  100 files and so can be read in one initial chunk or has more than 1000
 
46
  files and so big increment are suitable.
 
47
*/
 
48
#define ENTRIES_START_SIZE (8192/sizeof(FILEINFO))
 
49
#define ENTRIES_INCREMENT  (65536/sizeof(FILEINFO))
 
50
#define NAMES_START_SIZE   32768
 
51
 
 
52
 
 
53
static int comp_names(const struct fileinfo *a, const struct fileinfo *b);
 
54
 
 
55
 
 
56
        /* We need this because program don't know with malloc we used */
 
57
 
 
58
void my_dirend(MY_DIR *buffer)
 
59
{
 
60
  if (buffer)
 
61
  {
 
62
    delete_dynamic((DYNAMIC_ARRAY*)((char*)buffer +
 
63
                                    ALIGN_SIZE(sizeof(MY_DIR))));
 
64
    free_root((MEM_ROOT*)((char*)buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
 
65
                          ALIGN_SIZE(sizeof(DYNAMIC_ARRAY))), MYF(0));
 
66
    free((unsigned char*) buffer);
 
67
  }
 
68
  return;
 
69
} /* my_dirend */
 
70
 
 
71
 
 
72
        /* Compare in sort of filenames */
 
73
 
 
74
static int comp_names(const struct fileinfo *a, const struct fileinfo *b)
 
75
{
 
76
  return (strcmp(a->name,b->name));
 
77
} /* comp_names */
 
78
 
 
79
 
 
80
MY_DIR  *my_dir(const char *path, myf MyFlags)
 
81
{
 
82
  char          *buffer;
 
83
  MY_DIR        *result= 0;
 
84
  FILEINFO      finfo;
 
85
  DYNAMIC_ARRAY *dir_entries_storage;
 
86
  MEM_ROOT      *names_storage;
 
87
  DIR           *dirp;
 
88
  struct dirent *dp;
 
89
  char          tmp_path[FN_REFLEN+1],*tmp_file;
 
90
  char  dirent_tmp[sizeof(struct dirent)+_POSIX_PATH_MAX+1];
 
91
 
 
92
  dirp = opendir(directory_file_name(tmp_path,(char *) path));
 
93
  if (dirp == NULL ||
 
94
      ! (buffer= (char *) malloc(ALIGN_SIZE(sizeof(MY_DIR)) + 
 
95
                                 ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)) +
 
96
                                 sizeof(MEM_ROOT))))
 
97
    goto error;
 
98
 
 
99
  dir_entries_storage= (DYNAMIC_ARRAY*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)));
 
100
  names_storage= (MEM_ROOT*)(buffer + ALIGN_SIZE(sizeof(MY_DIR)) +
 
101
                             ALIGN_SIZE(sizeof(DYNAMIC_ARRAY)));
 
102
 
 
103
  if (my_init_dynamic_array(dir_entries_storage, sizeof(FILEINFO),
 
104
                            ENTRIES_START_SIZE, ENTRIES_INCREMENT))
 
105
  {
 
106
    free((unsigned char*) buffer);
 
107
    goto error;
 
108
  }
 
109
  init_alloc_root(names_storage, NAMES_START_SIZE, NAMES_START_SIZE);
 
110
 
 
111
  /* MY_DIR structure is allocated and completly initialized at this point */
 
112
  result= (MY_DIR*)buffer;
 
113
 
 
114
  tmp_file= strchr(tmp_path, '\0');
 
115
 
 
116
  dp= (struct dirent*) dirent_tmp;
 
117
 
 
118
  while (!(READDIR(dirp,(struct dirent*) dirent_tmp,dp)))
 
119
  {
 
120
    if (!(finfo.name= strdup_root(names_storage, dp->d_name)))
 
121
      goto error;
 
122
 
 
123
    if (MyFlags & MY_WANT_STAT)
 
124
    {
 
125
      if (!(finfo.mystat= (struct stat*)alloc_root(names_storage,
 
126
                                               sizeof(struct stat))))
 
127
        goto error;
 
128
 
 
129
      memset(finfo.mystat, 0, sizeof(struct stat));
 
130
      strcpy(tmp_file,dp->d_name);
 
131
      stat(tmp_path, finfo.mystat);
 
132
      if (!(finfo.mystat->st_mode & S_IREAD))
 
133
        continue;
 
134
    }
 
135
    else
 
136
      finfo.mystat= NULL;
 
137
 
 
138
    if (push_dynamic(dir_entries_storage, (unsigned char*)&finfo))
 
139
      goto error;
 
140
  }
 
141
 
 
142
  (void) closedir(dirp);
 
143
 
 
144
  result->dir_entry= (FILEINFO *)dir_entries_storage->buffer;
 
145
  result->number_off_files= dir_entries_storage->elements;
 
146
 
 
147
  if (!(MyFlags & MY_DONT_SORT))
 
148
    my_qsort((void *) result->dir_entry, result->number_off_files,
 
149
          sizeof(FILEINFO), (qsort_cmp) comp_names);
 
150
  return(result);
 
151
 
 
152
 error:
 
153
 
 
154
  my_errno=errno;
 
155
  if (dirp)
 
156
    (void) closedir(dirp);
 
157
  my_dirend(result);
 
158
  if (MyFlags & (MY_FAE | MY_WME))
 
159
    my_error(EE_DIR,MYF(ME_BELL+ME_WAITTANG),path,my_errno);
 
160
 
 
161
  return((MY_DIR *) NULL);
 
162
} /* my_dir */
 
163
 
 
164
 
 
165
/*
 
166
 * Convert from directory name to filename.
 
167
 * On VMS:
 
168
 *       xyzzy:[mukesh.emacs] => xyzzy:[mukesh]emacs.dir.1
 
169
 *       xyzzy:[mukesh] => xyzzy:[000000]mukesh.dir.1
 
170
 * On UNIX, it's simple: just make sure there is a terminating /
 
171
 
 
172
 * Returns pointer to dst;
 
173
 */
 
174
 
 
175
char * directory_file_name (char * dst, const char *src)
 
176
{
 
177
  /* Process as Unix format: just remove test the final slash. */
 
178
 
 
179
  char * end;
 
180
 
 
181
  if (src[0] == 0)
 
182
    src= (char*) ".";                           /* Use empty as current */
 
183
  end= strcpy(dst, src)+strlen(src);
 
184
  if (end[-1] != FN_LIBCHAR)
 
185
  {
 
186
    end[0]=FN_LIBCHAR;                          /* Add last '/' */
 
187
    end[1]='\0';
 
188
  }
 
189
  return dst;
 
190
} /* directory_file_name */
 
191