GRASS GIS 8 Programmer's Manual  8.5.0dev(2024)-d6dec75dd4
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 #define R_OK 4
26 #endif
27 #ifndef W_OK
28 #define W_OK 2
29 #endif
30 #ifndef X_OK
31 #define X_OK 1
32 #endif
33 
34 static int cmp_dirent(const void *, const void *);
35 static int get_perm(char *);
36 static void sort_dirent(dbDirent *, int);
37 
38 /*!
39  \brief Read directory and build an array of dbDirent's
40 
41  Append one entry with name = NULL to mark end of array
42 
43  \param dirname directory name
44  \param[out] n number of entities
45 
46  \return pointer to dbDirent
47  \return NULL on error
48  */
49 dbDirent *db_dirent(const char *dirname, int *n)
50 {
51  DIR *dp;
52  struct dirent *entry;
54  int i, count;
55  char *path;
56  int len, max;
57 
59 
60  *n = 0;
61  dp = opendir(dirname);
62  if (dp == NULL) {
63  db_syserror(dirname);
64  return (dbDirent *)NULL;
65  }
66 
67  /* count the number of entries and get the strlen of the longest name */
68  count = 0;
69  max = 0;
70  while ((entry = readdir(dp))) {
71  count++;
72  len = strlen(entry->d_name);
73  if (len > max)
74  max = len;
75  }
76  rewinddir(dp);
77 
78  path = db_malloc(strlen(dirname) + max + 2); /* extra 2 for / and NULL */
79  if (path == NULL) {
80  closedir(dp);
81  return (dbDirent *)NULL;
82  }
84  if (db_dirent == NULL) {
85  closedir(dp);
86  return (dbDirent *)NULL;
87  }
88  *n = count;
89  for (i = 0; i < count; i++) {
90  entry = readdir(dp);
91  if (entry == NULL) /* this shouldn't happen */
92  break;
93 
94  if (DB_OK != db_set_string(&db_dirent[i].name, entry->d_name))
95  break;
96  sprintf(path, "%s/%s", dirname, entry->d_name);
97  db_dirent[i].perm = get_perm(path);
98  db_dirent[i].isdir = (db_isdir(path) == DB_OK);
99  }
100  closedir(dp);
101  db_free(path);
102 
103  sort_dirent(db_dirent, *n);
104 
105  return db_dirent;
106 }
107 
108 /*!
109  \brief Free dbDirent
110 
111  \param db_dirent pointer to dbDirent
112  \param count number of entities in the array
113  */
115 {
116  int i;
117 
118  if (db_dirent) {
119  for (i = 0; i < count; i++)
122  }
123 }
124 
125 static int get_perm(char *path)
126 {
127  int perm;
128 
129  perm = 0;
130 
131  if (access(path, R_OK) == 0)
132  perm |= DB_PERM_R;
133  if (access(path, W_OK) == 0)
134  perm |= DB_PERM_W;
135  if (access(path, X_OK) == 0)
136  perm |= DB_PERM_X;
137 
138  return perm;
139 }
140 
141 static int cmp_dirent(const void *aa, const void *bb)
142 {
143  const dbDirent *a = aa;
144  const dbDirent *b = bb;
145 
146  return strcmp(db_get_string((dbString *)&a->name),
147  db_get_string((dbString *)&b->name));
148 }
149 
150 static void sort_dirent(dbDirent *a, int n)
151 {
152  qsort(a, n, sizeof(dbDirent), cmp_dirent);
153 }
154 
155 /*!
156  \brief Allocate dirent array
157 
158  \param count number of entities in the array
159 
160  \return pointer to dbDirent array
161  \return NULL on failure
162  */
164 {
165  int i;
167 
168  db_dirent = (dbDirent *)db_calloc(count, sizeof(dbDirent));
169  if (db_dirent == NULL)
170  return db_dirent;
171 
172  for (i = 0; i < count; i++)
174 
175  return db_dirent;
176 }
#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.
#define R_OK
Definition: dirent.c:25
#define X_OK
Definition: dirent.c:31
dbDirent * db_dirent(const char *dirname, int *n)
Read directory and build an array of dbDirent's.
Definition: dirent.c:49
dbDirent * db_alloc_dirent_array(int count)
Allocate dirent array.
Definition: dirent.c:163
void db_free_dirent_array(dbDirent *db_dirent, int count)
Free dbDirent.
Definition: dirent.c:114
#define W_OK
Definition: dirent.c:28
#define max(x, y)
Definition: draw2.c:30
int count
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: path.h:15