GRASS Programmer's Manual  6.4.2(2012)
dirent.c
Go to the documentation of this file.
00001 #include <string.h>
00002 #include <stdlib.h>
00003 #include <unistd.h>
00004 #include <grass/dbmi.h>
00005 /* NOTE: these should come from <unistd.h> or from <sys/file.h> */
00006 #define R_OK 4
00007 #define W_OK 2
00008 #define X_OK 1
00009 
00010 #include <sys/types.h>
00011 #ifdef USE_DIRECT
00012 # include <sys/dir.h>
00013 typedef struct direct dir_entry;
00014 #else
00015 # include <dirent.h>
00016 typedef struct dirent dir_entry;
00017 #endif
00018 
00019 extern DIR *opendir();
00020 extern dir_entry *readdir();
00021 
00022 static int get_perm();
00023 static void sort_dirent();
00024 
00025 
00032 /* read directory and build an array of dbDirent's */
00033 /* append one entry with name = NULL to mark end of array */
00034 dbDirent *db_dirent(const char *dirname, int *n)
00035 {
00036     DIR *dp;
00037     dir_entry *entry;
00038     dbDirent *dirent;
00039     int i, count;
00040     char *path;
00041     int len, max;
00042 
00043     db_clear_error();
00044 
00045     *n = 0;
00046     dp = opendir(dirname);
00047     if (dp == NULL) {
00048         db_syserror(dirname);
00049         return (dbDirent *) NULL;
00050     }
00051 
00052 
00053     /* count the number of entries and get the strlen of the longest name */
00054     count = 0;
00055     max = 0;
00056     while ((entry = readdir(dp))) {
00057         count++;
00058         len = strlen(entry->d_name);
00059         if (len > max)
00060             max = len;
00061     }
00062     rewinddir(dp);
00063 
00064     path = db_malloc(strlen(dirname) + max + 2);        /* extra 2 for / and NULL */
00065     if (path == NULL) {
00066         closedir(dp);
00067         return (dbDirent *) NULL;
00068     }
00069     dirent = db_alloc_dirent_array(count);
00070     if (dirent == NULL) {
00071         closedir(dp);
00072         return (dbDirent *) NULL;
00073     }
00074     *n = count;
00075     for (i = 0; i < count; i++) {
00076         entry = readdir(dp);
00077         if (entry == NULL)      /* this shouldn't happen */
00078             break;
00079 
00080         if (DB_OK != db_set_string(&dirent[i].name, entry->d_name))
00081             break;
00082         sprintf(path, "%s/%s", dirname, entry->d_name);
00083         dirent[i].perm = get_perm(path);
00084         dirent[i].isdir = (db_isdir(path) == DB_OK);
00085     }
00086     closedir(dp);
00087     db_free(path);
00088 
00089     sort_dirent(dirent, *n);
00090 
00091     return dirent;
00092 }
00093 
00100 void db_free_dirent_array(dbDirent * dirent, int count)
00101 {
00102     int i;
00103 
00104     if (dirent) {
00105         for (i = 0; i < count; i++)
00106             db_free_string(&dirent[i].name);
00107         db_free(dirent);
00108     }
00109 }
00110 
00111 static int get_perm(char *path)
00112 {
00113     int perm;
00114 
00115     perm = 0;
00116 
00117     if (access(path, R_OK) == 0)
00118         perm |= DB_PERM_R;
00119     if (access(path, W_OK) == 0)
00120         perm |= DB_PERM_W;
00121     if (access(path, X_OK) == 0)
00122         perm |= DB_PERM_X;
00123 
00124     return perm;
00125 }
00126 
00127 static int cmp_dirent(const void *aa, const void *bb)
00128 {
00129     const dbDirent *a = aa;
00130     const dbDirent *b = bb;
00131 
00132     return strcmp(db_get_string((dbString *) & a->name),
00133                   db_get_string((dbString *) & b->name));
00134 }
00135 
00136 static void sort_dirent(dbDirent * a, int n)
00137 {
00138     qsort(a, n, sizeof(dbDirent), cmp_dirent);
00139 }
00140 
00147 dbDirent *db_alloc_dirent_array(int count)
00148 {
00149     int i;
00150     dbDirent *dirent;
00151 
00152     dirent = (dbDirent *) db_calloc(count, sizeof(dbDirent));
00153     if (dirent == NULL)
00154         return dirent;
00155 
00156     for (i = 0; i < count; i++)
00157         db_init_string(&dirent[i].name);
00158 
00159     return dirent;
00160 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines