GRASS Programmer's Manual
6.4.2(2012)
|
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 }