dirent.c 3.6 KB

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