123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209 |
- #include <errno.h>
- #include <dirent.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <string.h>
- #include "lmdb.h"
- #include "volksdata/core.h"
- bool VOLK_env_is_init = false;
- /** @brief Warning messages.
- *
- * The message corresponding to the rc is found by
- * warning_msg[rc - VOLK_MIN_WARNING]. #VOLK_strerror() facilitates this.
- */
- char *warning_msg[] = {
- "VOLK_NOACTION: No action or change of state occurred.",
- "VOLK_NORESULT: No result.",
- "VOLK_END: End of the loop reached.",
- "VOLK_CONFLICT: A conflict prevented a resource from being updated.",
- };
- /** @brief error messages.
- *
- * Note that all error values are < 0 so it is possible to set conditions to
- * be triggered only by error return values.
- *
- * The message corresponding to the rc is found by
- * err_msg[rc - VOLK_MIN_ERROR]. #VOLK_strerror() facilitates this.
- */
- char *err_msg[] = {
- "VOLK_ERROR: Runtime error.",
- "VOLK_PARSE_ERR: Error parsing input.",
- "VOLK_VALUE_ERR: Invalid input.",
- "VOLK_TXN_ERR: MDB transaction error.",
- "VOLK_DB_ERR: Database error.",
- "VOLK_NOT_IMPL_ERR: Feature is not implemented.",
- "VOLK_IO_ERR: Input/Output error.",
- "VOLK_MEM_ERR: Memory error.",
- "VOLK_CONFLICT_ERR: A resource conflict interrupted the operation.",
- "VOLK_ENV_ERR: Environment not initialized. Did you call VOLK_init()?",
- };
- char *VOLK_root_path = __FILE__; // This is trimmed to root path on init.
- VOLK_rc
- mkdir_p (const char *_path, mode_t mode)
- {
- char *path = strdup (_path);
- char *p;
- // Trim any trailing slash(es).
- for (p = path + strlen (path) - 1; p > path; p--)
- if (*p == '/') *p = '\0';
- else break;
- errno = 0;
- VOLK_rc rc = VOLK_NOACTION;
- /* Iterate the string */
- for (p = path + 1; *p; p++) {
- if (*p == '/') {
- /* Temporarily truncate */
- *p = '\0';
- if (mkdir (path, mode) != 0 && errno != EEXIST) goto finally;
- *p = '/';
- }
- }
- if (mkdir (path, mode) != 0) {
- if (errno != EEXIST) rc = errno;
- } else {
- rc = VOLK_OK;
- }
- finally:
- LOG_TRACE("Path: %s", path);
- LOG_TRACE("errno: %d", errno);
- LOG_TRACE("rc: %d", rc);
- free (path);
- return rc;
- }
- char *
- strndup (const char *src, size_t max)
- {
- size_t len = strlen (src);
- if (len > max) len = max;
- char *dup;
- dup = malloc (len + 1);
- if (dup) {
- memcpy (dup, src, len);
- dup[len] = '\0';
- }
- return dup;
- }
- char *
- strdup (const char *src)
- {
- char *dup;
- dup = malloc (strlen (src) + 1);
- if (dup) strcpy(dup, src);
- return dup;
- }
- /** @brief Remove a directory recursively (POSIX compatible).
- *
- * Adapted from
- * https://stackoverflow.com/questions/5467725/how-to-delete-a-directory-and-its-contents-in-posix-c/42596507#42596507
- */
- VOLK_rc rm_r (const char *path)
- {
- size_t path_len;
- char *full_path;
- DIR *dir;
- struct stat stat_path, stat_entry;
- struct dirent *entry;
- // stat for the path
- stat(path, &stat_path);
- // if path does not exists or is not dir - exit with status -1
- if (S_ISDIR(stat_path.st_mode) == 0) {
- log_error ("%s: %s\n", "Is not directory", path);
- return VOLK_IO_ERR;
- }
- // if not possible to read the directory for this user
- if ((dir = opendir(path)) == NULL) {
- log_error ("%s: %s\n", "Can`t open directory", path);
- return VOLK_IO_ERR;
- }
- // the length of the path
- path_len = strlen(path);
- // iteration through entries in the directory
- while ((entry = readdir(dir)) != NULL) {
- // skip entries "." and ".."
- if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
- continue;
- // determine a full path of an entry
- full_path = calloc(
- path_len + 1 + strlen(entry->d_name) + 1, sizeof(char));
- strcpy(full_path, path);
- strcat(full_path, "/");
- strcat(full_path, entry->d_name);
- // stat for the entry
- stat(full_path, &stat_entry);
- // recursively remove a nested directory
- if (S_ISDIR(stat_entry.st_mode) != 0) {
- rm_r (full_path);
- free (full_path);
- continue;
- }
- // remove a file object
- if (unlink(full_path) == 0)
- LOG_DEBUG ("Removed a file:\t%s\n", full_path);
- else
- log_error ("Can't remove a file:\t%s\n", full_path);
- free(full_path);
- }
- // remove the devastated directory and close the object of it
- if (rmdir(path) == 0)
- LOG_DEBUG ("Removed a directory:\t%s\n", path);
- else
- log_error ("Can't remove a directory:\t%s\n", path);
- closedir(dir);
- return VOLK_OK;
- }
- const char *
- VOLK_strerror (VOLK_rc rc)
- {
- if (rc >= VOLK_MIN_ERROR && rc <= VOLK_MAX_ERROR)
- return err_msg[rc - VOLK_MIN_ERROR];
- if (rc >= VOLK_MIN_WARNING && rc <= VOLK_MAX_WARNING)
- return warning_msg[rc - VOLK_MIN_WARNING];
- return mdb_strerror (rc);
- }
- /* Inline extern functions. */
- int utf8_encode (const uint32_t utf, unsigned char *out);
|