GRASS GIS 7 Programmer's Manual  7.9.dev(2021)-a1cfe415e
dirent.c
Go to the documentation of this file.
1 /*!
2  \file lib/db/dbmi_base/dirent.c
3 
4  \brief DBMI Library (base) - directory entities management
5 
6  (C) 1999-2010 by the GRASS Development Team
7 
8  This program is free software under the GNU General Public License
9  (>=v2). Read the file COPYING that comes with GRASS for details.
10 
11  \author Joel Jones (CERL/UIUC)
12  \author Upgraded to GRASS 5.7 by Radim Blazek
13 */
14 
15 #include <string.h>
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <grass/dbmi.h>
19 /* NOTE: these should come from <unistd.h> or from <sys/file.h> */
20 #ifndef R_OK
21 #define R_OK 4
22 #endif
23 #ifndef W_OK
24 #define W_OK 2
25 #endif
26 #ifndef X_OK
27 #define X_OK 1
28 #endif
29 
30 #include <sys/types.h>
31 #ifdef USE_DIRECT
32 # include <sys/dir.h>
33 typedef struct direct dir_entry;
34 #else
35 # include <dirent.h>
36 typedef struct dirent dir_entry;
37 #endif
38 
39 extern DIR *opendir();
40 extern dir_entry *readdir();
41 
42 static int cmp_dirent(const void *, const void *);
43 static int get_perm(char *);
44 static void sort_dirent(dbDirent *, int);
45 
46 /*!
47  \brief Read directory and build an array of dbDirent's
48 
49  Append one entry with name = NULL to mark end of array
50 
51  \param dirname directory name
52  \param[out] n number of entities
53 
54  \return pointer to dbDirent
55  \return NULL on error
56 */
57 dbDirent *db_dirent(const char *dirname, int *n)
58 {
59  DIR *dp;
60  dir_entry *entry;
61  dbDirent *dirent;
62  int i, count;
63  char *path;
64  int len, max;
65 
67 
68  *n = 0;
69  dp = opendir(dirname);
70  if (dp == NULL) {
71  db_syserror(dirname);
72  return (dbDirent *) NULL;
73  }
74 
75 
76  /* count the number of entries and get the strlen of the longest name */
77  count = 0;
78  max = 0;
79  while ((entry = readdir(dp))) {
80  count++;
81  len = strlen(entry->d_name);
82  if (len > max)
83  max = len;
84  }
85  rewinddir(dp);
86 
87  path = db_malloc(strlen(dirname) + max + 2); /* extra 2 for / and NULL */
88  if (path == NULL) {
89  closedir(dp);
90  return (dbDirent *) NULL;
91  }
92  dirent = db_alloc_dirent_array(count);
93  if (dirent == NULL) {
94  closedir(dp);
95  return (dbDirent *) NULL;
96  }
97  *n = count;
98  for (i = 0; i < count; i++) {
99  entry = readdir(dp);
100  if (entry == NULL) /* this shouldn't happen */
101  break;
102 
103  if (DB_OK != db_set_string(&dirent[i].name, entry->d_name))
104  break;
105  sprintf(path, "%s/%s", dirname, entry->d_name);
106  dirent[i].perm = get_perm(path);
107  dirent[i].isdir = (db_isdir(path) == DB_OK);
108  }
109  closedir(dp);
110  db_free(path);
111 
112  sort_dirent(dirent, *n);
113 
114  return dirent;
115 }
116 
117 /*!
118  \brief Free dbDirent
119 
120  \param dirent pointer to dbDirent
121  \param count number of entities in the array
122 */
124 {
125  int i;
126 
127  if (dirent) {
128  for (i = 0; i < count; i++)
129  db_free_string(&dirent[i].name);
130  db_free(dirent);
131  }
132 }
133 
134 static int get_perm(char *path)
135 {
136  int perm;
137 
138  perm = 0;
139 
140  if (access(path, R_OK) == 0)
141  perm |= DB_PERM_R;
142  if (access(path, W_OK) == 0)
143  perm |= DB_PERM_W;
144  if (access(path, X_OK) == 0)
145  perm |= DB_PERM_X;
146 
147  return perm;
148 }
149 
150 static int cmp_dirent(const void *aa, const void *bb)
151 {
152  const dbDirent *a = aa;
153  const dbDirent *b = bb;
154 
155  return strcmp(db_get_string((dbString *) & a->name),
156  db_get_string((dbString *) & b->name));
157 }
158 
159 static void sort_dirent(dbDirent * a, int n)
160 {
161  qsort(a, n, sizeof(dbDirent), cmp_dirent);
162 }
163 
164 /*!
165  \brief Allocate dirent array
166 
167  \param count number of entities in the array
168 
169  \return pointer to dbDirent array
170  \return NULL on failure
171 */
173 {
174  int i;
175  dbDirent *dirent;
176 
177  dirent = (dbDirent *) db_calloc(count, sizeof(dbDirent));
178  if (dirent == NULL)
179  return dirent;
180 
181  for (i = 0; i < count; i++)
182  db_init_string(&dirent[i].name);
183 
184  return dirent;
185 }
DIR * opendir()
void db_syserror(const char *s)
Report system error.
#define DB_PERM_X
Definition: dbmi.h:68
void * db_malloc(int n)
Allocate memory.
dbString name
Definition: dbmi.h:163
int count
dbDirent * db_dirent(const char *dirname, int *n)
Read directory and build an array of dbDirent&#39;s.
Definition: dirent.c:57
void db_clear_error(void)
Clear error status.
#define R_OK
Definition: dirent.c:21
#define NULL
Definition: ccmath.h:32
#define W_OK
Definition: dirent.c:24
#define max(x, y)
Definition: draw2.c:32
char * db_get_string(const dbString *x)
Get string.
Definition: string.c:140
int perm
Definition: dbmi.h:165
dir_entry * readdir()
#define DB_PERM_R
Definition: dbmi.h:66
void db_free_dirent_array(dbDirent *dirent, int count)
Free dbDirent.
Definition: dirent.c:123
double b
Definition: r_raster.c:39
void * db_calloc(int n, int m)
Allocate memory.
#define X_OK
Definition: dirent.c:27
#define DB_PERM_W
Definition: dbmi.h:67
dbDirent * db_alloc_dirent_array(int count)
Allocate dirent array.
Definition: dirent.c:172
Definition: path.h:16
int db_set_string(dbString *x, const char *s)
Inserts string to dbString (enlarge string)
Definition: string.c:41
int isdir
Definition: dbmi.h:164
int db_isdir(const char *path)
Test if path is a directory.
Definition: isdir.c:29
const char * name
Definition: named_colr.c:7
void db_free_string(dbString *x)
Free allocated space for dbString.
Definition: string.c:150
struct dirent dir_entry
Definition: dirent.c:36
void db_init_string(dbString *x)
Initialize dbString.
Definition: string.c:25
void db_free(void *s)
Free allocated memory.
#define DB_OK
Definition: dbmi.h:71