~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/internal/my_lib.cc

  • Committer: Brian Aker
  • Date: 2010-01-04 00:33:03 UTC
  • mfrom: (1259.3.7 remove-mydir)
  • Revision ID: brian@gaz-20100104003303-wkp8mbm5991kxro8
Merge Monty

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