GRASS GIS 8 Programmer's Manual  8.5.0dev(2025)-565e82de51
lib/db/dbmi_base/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 <sys/types.h>
19 #include <dirent.h>
20 
21 #include <grass/dbmi.h>
22 
23 /* NOTE: these should come from <unistd.h> or from <sys/file.h> */
24 #ifndef R_OK
25 #if !defined(HAVE_UNISTD_H)
26 #define R_OK 4
27 #endif
28 #ifndef W_OK
29 #define W_OK 2
30 #endif
31 #ifndef X_OK
32 #define X_OK 1
33 #endif
34 #endif
35 
36 static int cmp_dirent(const void *, const void *);
37 static int get_perm(char *);
38 static void sort_dirent(dbDirent *, int);
39 
40 /*!
41  \brief Read directory and build an array of dbDirent's
42 
43  Append one entry with name = NULL to mark end of array
44 
45  \param dirname directory name
46  \param[out] n number of entities
47 
48  \return pointer to dbDirent
49  \return NULL on error
50  */
51 dbDirent *db_dirent(const char *dirname, int *n)
52 {
53  DIR *dp;
54  struct dirent *entry;
56  int i, count;
57  char *path;
58  int len, max;
59 
61 
62  *n = 0;
63  dp = opendir(dirname);
64  if (dp == NULL) {
65  db_syserror(dirname);
66  return (dbDirent *)NULL;
67  }
68 
69  /* count the number of entries and get the strlen of the longest name */
70  count = 0;
71  max = 0;
72  while ((entry = readdir(dp))) {
73  count++;
74  len = strlen(entry->d_name);
75  if (len > max)
76  max = len;
77  }
78  rewinddir(dp);
79 
80  path = db_malloc(strlen(dirname) + max + 2); /* extra 2 for / and NULL */
81  if (path == NULL) {
82  closedir(dp);
83  return (dbDirent *)NULL;
84  }
86  if (db_dirent == NULL) {
87  closedir(dp);
88  return (dbDirent *)NULL;
89  }
90  *n = count;
91  for (i = 0; i < count; i++) {
92  entry = readdir(dp);
93  if (entry == NULL) /* this shouldn't happen */
94  break;
95 
96  if (DB_OK != db_set_string(&db_dirent[i].name, entry->d_name))
97  break;
98  sprintf(path, "%s/%s", dirname, entry->d_name);
99  db_dirent[i].perm = get_perm(path);
100  db_dirent[i].isdir = (db_isdir(path) == DB_OK);
101  }
102  closedir(dp);
103  db_free(path);
104 
105  sort_dirent(db_dirent, *n);
106 
107  return db_dirent;
108 }
109 
110 /*!
111  \brief Free dbDirent
112 
113  \param db_dirent pointer to dbDirent
114  \param count number of entities in the array
115  */
117 {
118  int i;
119 
120  if (db_dirent) {
121  for (i = 0; i < count; i++)
124  }
125 }
126 
127 static int get_perm(char *path)
128 {
129  int perm;
130 
131  perm = 0;
132 
133  if (access(path, R_OK) == 0)
134  perm |= DB_PERM_R;
135  if (access(path, W_OK) == 0)
136  perm |= DB_PERM_W;
137  if (access(path, X_OK) == 0)
138  perm |= DB_PERM_X;
139 
140  return perm;
141 }
142 
143 static int cmp_dirent(const void *aa, const void *bb)
144 {
145  const dbDirent *a = aa;
146  const dbDirent *b = bb;
147 
148  return strcmp(db_get_string((dbString *)&a->name),
149  db_get_string((dbString *)&b->name));
150 }
151 
152 static void sort_dirent(dbDirent *a, int n)
153 {
154  qsort(a, n, sizeof(dbDirent), cmp_dirent);
155 }
156 
157 /*!
158  \brief Allocate dirent array
159 
160  \param count number of entities in the array
161 
162  \return pointer to dbDirent array
163  \return NULL on failure
164  */
166 {
167  int i;
169 
170  db_dirent = (dbDirent *)db_calloc(count, sizeof(dbDirent));
171  if (db_dirent == NULL)
172  return db_dirent;
173 
174  for (i = 0; i < count; i++)
176 
177  return db_dirent;
178 }
#define NULL
Definition: ccmath.h:32
#define DB_PERM_R
Definition: dbmi.h:66
#define DB_PERM_X
Definition: dbmi.h:68
#define DB_PERM_W
Definition: dbmi.h:67
#define DB_OK
Definition: dbmi.h:71
int db_isdir(const char *)
Test if path is a directory.
Definition: isdir.c:29
void * db_calloc(int, int)
Allocate memory.
void db_clear_error(void)
Clear error status.
void db_free_string(dbString *)
Free allocated space for dbString.
Definition: string.c:150
int db_set_string(dbString *, const char *)
Inserts string to dbString (enlarge string)
Definition: string.c:41
void db_free(void *)
Free allocated memory.
void db_init_string(dbString *)
Initialize dbString.
Definition: string.c:25
void db_syserror(const char *)
Report system error.
char * db_get_string(const dbString *)
Get string.
Definition: string.c:140
void * db_malloc(int)
Allocate memory.
struct DIR DIR
Definition: dirent.h:18
#define max(x, y)
Definition: draw2.c:30
GRASS_INTERPFL_EXPORT int count
#define X_OK
dbDirent * db_dirent(const char *dirname, int *n)
Read directory and build an array of dbDirent's.
dbDirent * db_alloc_dirent_array(int count)
Allocate dirent array.
void db_free_dirent_array(dbDirent *db_dirent, int count)
Free dbDirent.
#define W_OK
DIR * opendir(const char *name)
Definition: msvc/dirent.c:15
void rewinddir(DIR *dir)
Definition: msvc/dirent.c:92
int closedir(DIR *dir)
Definition: msvc/dirent.c:54
struct dirent * readdir(DIR *dir)
Definition: msvc/dirent.c:75
const char * name
Definition: named_colr.c:6
double b
Definition: r_raster.c:39
dbString name
Definition: dbmi.h:160
int perm
Definition: dbmi.h:162
int isdir
Definition: dbmi.h:161
Definition: dirent.h:20
char * d_name
Definition: dirent.h:21
Definition: path.h:15
#define access
Definition: unistd.h:7
#define R_OK
Definition: unistd.h:25