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