#include "dir.h" #include #include #include #if defined(PAL_HAVE_POSIX) # include # include # include # include #endif #if defined(_MSC_VER) # include # include # include #endif /* **============================================================================== ** ** Dir type (POSIX) ** **============================================================================== */ #if defined(PAL_HAVE_POSIX) struct _Dir { DIR* dir; DirEnt ent; }; Dir* Dir_Open(const char* path) { Dir* self = (Dir*)PAL_Calloc(1, sizeof(Dir)); if (!self) return NULL; self->dir = opendir(path); if (!self->dir) { PAL_Free(self); return NULL; } return self; } DirEnt* Dir_Read(Dir* self) { struct dirent* p = readdir(self->dir); if (!p) return NULL; Strlcpy(self->ent.name, p->d_name, sizeof(self->ent.name)); return &self->ent; } int Dir_Close(Dir* self) { if (!self) return -1; if (closedir(self->dir) != 0) { PAL_Free(self); return -1; } PAL_Free(self); return 0; } #endif /* defined(PAL_HAVE_POSIX) */ /* **============================================================================== ** ** Dir type (Windows) ** **============================================================================== */ #if defined(_MSC_VER) struct _Dir { intptr_t handle; struct _finddata_t fileinfo; DirEnt ent; int firstTime; }; Dir* Dir_Open(const char* path) { Dir* dir; char filespec[PAL_MAX_PATH_SIZE]; /* Allocate and zero-fill struct */ dir = (Dir*)PAL_Calloc(1, sizeof(Dir)); if (!dir) return NULL; /* Build files spec */ { if (Strlcpy(filespec, path, sizeof(filespec)) >= PAL_MAX_PATH_SIZE) return NULL; if (Strlcat(filespec, "/*", sizeof(filespec)) >= PAL_MAX_PATH_SIZE) return NULL; } /* Find first file matching the file spec */ dir->handle = _findfirst(filespec, &dir->fileinfo); if (dir->handle == -1) { PAL_Free(dir); return NULL; } /* Note that readdir() has not been called yet */ dir->firstTime = 1; return dir; } DirEnt* Dir_Read(Dir* dir) { if (!dir->firstTime) { if (_findnext(dir->handle, &dir->fileinfo) != 0) return NULL; } Strlcpy(dir->ent.name, dir->fileinfo.name, PAL_MAX_PATH_SIZE); dir->firstTime = 0; return &dir->ent; } int Dir_Close(Dir* dir) { _findclose(dir->handle); PAL_Free(dir); return 0; } #endif /* defined(_MSC_VER) */ /* **============================================================================== ** ** Isdir() ** **============================================================================== */ PAL_Boolean Isdir(const char* path) { #if defined(_MSC_VER) { struct _stat st; if (_stat(path, &st) != 0) return 0; return (_S_IFDIR & st.st_mode) ? PAL_TRUE : PAL_FALSE; } #else { struct stat st; if (stat(path, &st) != 0) return 0; return S_ISDIR(st.st_mode); } #endif } const char* Basename(const char* path) { const char* p = strrchr(path, '/'); if (p) return p + 1; return path; } int Mkdirhier(const char* path_, int mode) { char path[PAL_MAX_PATH_SIZE]; char buf[PAL_MAX_PATH_SIZE]; char* p; char* context = NULL; /* Make a complete copy of the path (that we can destroy) */ if (Strlcpy(path, path_, sizeof(path)) >= sizeof(path)) return -1; buf[0] = '\0'; for (p = Strtok(path, "/", &context); p; p = Strtok(NULL, "/", &context)) { #if defined(CONFIG_OS_WINDOWS) /* Skip drive letters (on Windows) */ if (p == path && isalpha((unsigned char)p[0]) && p[1] == ':' && p[2] == '\0') { Strlcat(buf, p, sizeof(buf)); continue; } #endif /* Concatenate next component */ Strlcat(buf, "/", sizeof(buf)); Strlcat(buf, p, sizeof(buf)); /* Create directory if it does not already exist */ if (!Isdir(buf)) { if (Mkdir(buf, mode) != 0) return -1; } } return 0; }