dirent.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #include <string.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <grass/dbmi.h>
  5. /* NOTE: these should come from <unistd.h> or from <sys/file.h> */
  6. #define R_OK 4
  7. #define W_OK 2
  8. #define X_OK 1
  9. #include <sys/types.h>
  10. #ifdef USE_DIRECT
  11. # include <sys/dir.h>
  12. typedef struct direct dir_entry;
  13. #else
  14. # include <dirent.h>
  15. typedef struct dirent dir_entry;
  16. #endif
  17. extern DIR *opendir();
  18. extern dir_entry *readdir();
  19. static int get_perm();
  20. static void sort_dirent();
  21. /*!
  22. \fn
  23. \brief
  24. \return
  25. \param
  26. */
  27. /* read directory and build an array of dbDirent's */
  28. /* append one entry with name = NULL to mark end of array */
  29. dbDirent *db_dirent(const char *dirname, int *n)
  30. {
  31. DIR *dp;
  32. dir_entry *entry;
  33. dbDirent *dirent;
  34. int i, count;
  35. char *path;
  36. int len, max;
  37. db_clear_error();
  38. *n = 0;
  39. dp = opendir(dirname);
  40. if (dp == NULL) {
  41. db_syserror(dirname);
  42. return (dbDirent *) NULL;
  43. }
  44. /* count the number of entries and get the strlen of the longest name */
  45. count = 0;
  46. max = 0;
  47. while ((entry = readdir(dp))) {
  48. count++;
  49. len = strlen(entry->d_name);
  50. if (len > max)
  51. max = len;
  52. }
  53. rewinddir(dp);
  54. path = db_malloc(strlen(dirname) + max + 2); /* extra 2 for / and NULL */
  55. if (path == NULL) {
  56. closedir(dp);
  57. return (dbDirent *) NULL;
  58. }
  59. dirent = db_alloc_dirent_array(count);
  60. if (dirent == NULL) {
  61. closedir(dp);
  62. return (dbDirent *) NULL;
  63. }
  64. *n = count;
  65. for (i = 0; i < count; i++) {
  66. entry = readdir(dp);
  67. if (entry == NULL) /* this shouldn't happen */
  68. break;
  69. if (DB_OK != db_set_string(&dirent[i].name, entry->d_name))
  70. break;
  71. sprintf(path, "%s/%s", dirname, entry->d_name);
  72. dirent[i].perm = get_perm(path);
  73. dirent[i].isdir = (db_isdir(path) == DB_OK);
  74. }
  75. closedir(dp);
  76. free(path);
  77. sort_dirent(dirent, *n);
  78. return dirent;
  79. }
  80. /*!
  81. \fn
  82. \brief
  83. \return
  84. \param
  85. */
  86. void db_free_dirent_array(dbDirent * dirent, int count)
  87. {
  88. int i;
  89. if (dirent) {
  90. for (i = 0; i < count; i++)
  91. db_free_string(&dirent[i].name);
  92. free(dirent);
  93. }
  94. }
  95. static int get_perm(char *path)
  96. {
  97. int perm;
  98. perm = 0;
  99. if (access(path, R_OK) == 0)
  100. perm |= DB_PERM_R;
  101. if (access(path, W_OK) == 0)
  102. perm |= DB_PERM_W;
  103. if (access(path, X_OK) == 0)
  104. perm |= DB_PERM_X;
  105. return perm;
  106. }
  107. static int cmp_dirent(const void *aa, const void *bb)
  108. {
  109. const dbDirent *a = aa;
  110. const dbDirent *b = bb;
  111. return strcmp(db_get_string((dbString *) & a->name),
  112. db_get_string((dbString *) & b->name));
  113. }
  114. static void sort_dirent(dbDirent * a, int n)
  115. {
  116. qsort(a, n, sizeof(dbDirent), cmp_dirent);
  117. }
  118. /*!
  119. \fn
  120. \brief
  121. \return
  122. \param
  123. */
  124. dbDirent *db_alloc_dirent_array(int count)
  125. {
  126. int i;
  127. dbDirent *dirent;
  128. dirent = (dbDirent *) db_calloc(count, sizeof(dbDirent));
  129. if (dirent == NULL)
  130. return dirent;
  131. for (i = 0; i < count; i++)
  132. db_init_string(&dirent[i].name);
  133. return dirent;
  134. }