/* * AUTHOR * N. Nielsen * * LICENSE * This software is in the public domain. * * The software is provided "as is", without warranty of any kind, * express or implied, including but not limited to the warranties * of merchantability, fitness for a particular purpose, and * noninfringement. In no event shall the author(s) be liable for any * claim, damages, or other liability, whether in an action of * contract, tort, or otherwise, arising from, out of, or in connection * with the software or the use or other dealings in the software. * * SUPPORT * Send bug reports to: */ #include #include #include #include #include "common/compat.h" #include "file.h" #if HAVE_UNISTD_H && HAVE_DIRENT_H int is_dots(struct dirent* entry) { return entry->d_name && (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")); } int dir_next(DIR* handle, const char* wildcard, struct dirent* entry) { struct dirent* ent = 0; #ifndef HAVE_FNMATCH if(wildcard != NULL) { errno = EOPNOTSUPPORTED; return 0; } #endif if(!wildcard) wildcard = "*"; do { ent = readdir(handle); if(ent == NULL) { errno = ENOENT; break; } } #ifdef HAVE_FNMATCH while(is_dots(ent)); #else while(is_dots(ent) || fnmatch(wildcard, ent->d_name, FNM_PATHNAME) == FNM_NOMATCH); #endif if(ent) memcpy(entry, ent, sizeof(struct dirent)); return ent != NULL; } DIR* dir_first(const char* folder, const char* wildcard, struct dirent* entry) { DIR* handle = opendir((folder && strlen(folder) > 0) ? folder : "."); if(handle == NULL) return INVALID_DIR; if(dir_next(handle, wildcard, entry)) return handle; else { errno = ENOENT; dir_close(handle); return INVALID_DIR; } } void dir_close(DIR* handle) { closedir(handle); } #else #include #include int is_dots(struct _finddata_t* findinfo) { return findinfo->name && (!strcmp(findinfo->name, ".") || !strcmp(findinfo->name, "..")); } static void copyDirStruct(struct _finddata_t* findinfo, struct dirent* entry) { /* Copy the structure */ memset(entry, 0, sizeof(struct dirent)); entry->d_fileno = ~0; entry->d_reclen = ~0; strcpy(entry->d_name, findinfo->name); entry->d_namlen = strlen(findinfo->name); if(findinfo->attrib & _A_SUBDIR) entry->d_type |= DT_DIR; else entry->d_type |= DT_REG; } DIR* dir_first(const char* folder, const char* wildcard, struct dirent* entry) { DIR* handle; char buff[MAX_PATH * 2]; struct _finddata_t findinfo; if(!wildcard) wildcard = "*.*"; /* Check against buffer overflow hacks */ if(strlen(folder) + strlen(wildcard) + 1 > MAX_PATH * 2) { errno = ENAMETOOLONG; return INVALID_DIR; } if(!(handle = malloc(sizeof(DIR)))) { errno = ENOMEM; return INVALID_DIR; } strcpy(buff, folder); strcat(buff, strlen(folder) ? "\\" : ""); strcat(buff, wildcard); /* Okay get the first file */ *handle = _findfirst(buff, &findinfo); if(*handle == -1) { free(handle); return INVALID_DIR; } /* We don't do dots */ else if(is_dots(&findinfo)) { if(dir_next(handle, wildcard, entry)) return handle; errno = ENOENT; return INVALID_DIR; } /* Copy the first file */ else { copyDirStruct(&findinfo, entry); return handle; } } int dir_next(DIR* handle, const char* wildcard, struct dirent* entry) { struct _finddata_t findinfo; int ret = _findnext(*handle, &findinfo) == 0; if(ret) { if(is_dots(&findinfo)) return dir_next(handle, wildcard, entry); else copyDirStruct(&findinfo, entry); } return ret; } void dir_close(DIR* handle) { if(handle) { _findclose(*handle); free(handle); } } #endif const char* getFilename(const char* path) { const char* filename = strrchr(path, '\\'); const char* filename2 = strrchr(path, '/'); if(filename2 > filename) filename = filename2; return filename ? filename : path; } const char* getExtension(const char* path) { return strrchr(path, '.'); } int isDots(const char* path) { const char* filename = getFilename(path); return (filename[0] == '.' && (filename[1] == '.' || filename[1] == '\0')); } int isDirectory(const char* path) { struct stat st; if(stat(path, &st) == -1) return 0; return (st.st_mode & S_IFDIR) ? 1 : 0; }