1 /* file.h - file abstraction layer */ 2 #ifndef FILE_H 3 #define FILE_H 4 5 #include <stdint.h> 6 #include <stdio.h> 7 #include <wchar.h> /* for wchar_t */ 8 9 #ifdef __cplusplus 10 extern "C" { 11 #endif 12 13 #ifdef _WIN32 14 typedef wchar_t file_tchar; 15 # define SYS_PATH_SEPARATOR '\\' 16 # define ALIEN_PATH_SEPARATOR '/' 17 # define IS_PATH_SEPARATOR(c) ((c) == '\\' || (c) == '/') 18 # define IS_PATH_SEPARATOR_W(c) ((c) == L'\\' || (c) == L'/') 19 #else 20 typedef char file_tchar; 21 # define SYS_PATH_SEPARATOR '/' 22 # define ALIEN_PATH_SEPARATOR '\\' 23 # define IS_PATH_SEPARATOR(c) ((c) == '/') 24 #endif /* _WIN32 */ 25 typedef file_tchar* tpath_t; 26 typedef const file_tchar* ctpath_t; 27 28 /* Generic path functions */ 29 char* make_path(const char* dir, const char* filename, int user_path_separator); 30 #ifdef _WIN32 31 tpath_t make_wpath(ctpath_t dir_path, size_t dir_len, ctpath_t sub_path); 32 # define make_tpath(dir_path, sub_path) make_wpath(dir_path, (size_t)-1, sub_path) 33 #else 34 # define make_tpath(dir_path, sub_path) make_path(dir_path, sub_path, 0) 35 #endif /* _WIN32 */ 36 37 int is_regular_file(const char* path); /* shall be deprecated */ 38 39 /** 40 * Portable file information. 41 */ 42 typedef struct file_t 43 { 44 tpath_t real_path; 45 const char* print_path; 46 #ifdef _WIN32 47 const char* native_path; /* print_path in native encoding */ 48 #endif 49 char* data; 50 uint64_t size; 51 uint64_t mtime; 52 unsigned mode; 53 } file_t; 54 55 /* bit constants for the file_t.mode bit mask */ 56 enum FileModeBits { 57 FileIsDir = 0x01, 58 FileIsLnk = 0x02, 59 FileIsReg = 0x04, 60 FileIsInaccessible = 0x08, 61 FileIsRoot = 0x10, 62 FileIsData = 0x20, 63 FileIsList = 0x40, 64 FileIsStdStream = 0x80, 65 FileIsStdin = FileIsStdStream, 66 FileContentIsUtf8 = 0x100, 67 FileInitReusePath = 0x1000, 68 FileInitUtf8PrintPath = 0x2000, 69 FileInitRunFstat = 0x4000, 70 FileInitRunLstat = 0x8000, 71 FileInitUpdatePrintPathLastSlash = 0x10000, 72 FileInitUpdatePrintPathSlashes = 0x20000, 73 FileInitUseRealPathAsIs = 0x40000, 74 FileMaskUpdatePrintPath = (FileInitUpdatePrintPathLastSlash | FileInitUpdatePrintPathSlashes), 75 FileMaskStatBits = (FileIsDir | FileIsLnk | FileIsReg | FileIsInaccessible), 76 FileMaskIsSpecial = (FileIsData | FileIsList | FileIsStdStream), 77 FileMaskModeBits = (FileMaskStatBits | FileIsRoot | FileMaskIsSpecial | FileContentIsUtf8) 78 }; 79 80 #define FILE_ISDIR(file) ((file)->mode & FileIsDir) 81 #define FILE_ISLNK(file) ((file)->mode & FileIsLnk) 82 #define FILE_ISREG(file) ((file)->mode & FileIsReg) 83 #define FILE_ISBAD(file) ((file)->mode & FileIsInaccessible) 84 #define FILE_ISDATA(file) ((file)->mode & FileIsData) 85 #define FILE_ISLIST(file) ((file)->mode & FileIsList) 86 #define FILE_ISSTDIN(file) ((file)->mode & FileIsStdin) 87 #define FILE_ISSTDSTREAM(file) ((file)->mode & FileIsStdStream) 88 #define FILE_ISSPECIAL(file) ((file)->mode & (FileMaskIsSpecial)) 89 #define FILE_IS_IN_UTF8(file) ((file)->mode & (FileContentIsUtf8)) 90 91 /* file functions */ 92 int file_init(file_t* file, ctpath_t path, unsigned init_flags); 93 int file_init_by_print_path(file_t* file, file_t* prepend_dir, const char* print_path, unsigned init_flags); 94 void file_cleanup(file_t* file); 95 void file_clone(file_t* file, const file_t* orig_file); 96 void file_swap(file_t* first, file_t* second); 97 int are_paths_equal(ctpath_t path, struct file_t* file); 98 99 enum FileGetPrintPathFlags { 100 FPathPrimaryEncoding = 0, 101 FPathUtf8 = 1, 102 FPathNative = 2, 103 FPathBaseName = 4, 104 FPathNotNull = 8 105 }; 106 const char* file_get_print_path(file_t* file, unsigned flags); 107 108 enum FileModifyOperations { 109 FModifyAppendSuffix, 110 FModifyInsertBeforeExtension, 111 FModifyRemoveExtension, 112 FModifyGetParentDir 113 }; 114 int file_modify_path(file_t* dst, file_t* src, const char* str, int operation); 115 116 enum FileStatModes { 117 FNoMode = 0, 118 FUseLstat = FileInitRunLstat 119 }; 120 int file_stat(file_t* file, int fstat_flags); 121 122 enum FileFOpenModes { 123 FOpenRead = 1, 124 FOpenWrite = 2, 125 FOpenRW = 3, 126 FOpenBin = 4, 127 FOpenMask = 7 128 }; 129 FILE* file_fopen(file_t* file, int fopen_flags); 130 131 int file_rename(const file_t* from, const file_t* to); 132 int file_move_to_bak(file_t* file); 133 int file_is_readable(file_t* file); 134 135 /** 136 * A file list iterator. 137 */ 138 typedef struct file_list_t 139 { 140 FILE* fd; 141 file_t current_file; 142 unsigned state; 143 } file_list_t; 144 145 int file_list_open(file_list_t* list, file_t* file); 146 int file_list_read(file_list_t* list); 147 void file_list_close(file_list_t* list); 148 149 #ifndef _WIN32 150 # define dirent_get_tname(d) ((d)->d_name) 151 # define rsh_topendir(p) opendir(p) 152 #else 153 /* readdir structures and functions */ 154 # define DIR WIN_DIR 155 # define dirent win_dirent 156 # define opendir win_opendir 157 # define readdir win_readdir 158 # define closedir win_closedir 159 # define dirent_get_tname(d) ((d)->d_wname) 160 # define rsh_topendir(p) win_wopendir(p) 161 162 /* dirent struct for windows to traverse directory content */ 163 struct win_dirent 164 { 165 char* d_name; /* file name */ 166 wchar_t* d_wname; /* file name in Unicode (UTF-16) */ 167 int d_isdir; /* non-zero if file is a directory */ 168 }; 169 170 struct WIN_DIR_t; 171 typedef struct WIN_DIR_t WIN_DIR; 172 173 WIN_DIR* win_opendir(const char*); 174 WIN_DIR* win_wopendir(const wchar_t*); 175 struct win_dirent* win_readdir(WIN_DIR*); 176 void win_closedir(WIN_DIR*); 177 #endif 178 179 #ifdef __cplusplus 180 } /* extern "C" */ 181 #endif /* __cplusplus */ 182 183 #endif /* FILE_H */ 184