]>
Commit | Line | Data |
---|---|---|
ec250c6e | 1 | /* |
359fc2d2 | 2 | * Copyright (C) the libgit2 contributors. All rights reserved. |
ec250c6e | 3 | * |
bb742ede VM |
4 | * This file is part of libgit2, distributed under the GNU GPL v2 with |
5 | * a Linking Exception. For full terms see the included COPYING file. | |
ec250c6e AE |
6 | */ |
7 | #ifndef INCLUDE_fileops_h__ | |
8 | #define INCLUDE_fileops_h__ | |
9 | ||
5690f02e | 10 | #include "common.h" |
79ca2edc | 11 | #include "map.h" |
f79026b4 VM |
12 | #include "posix.h" |
13 | #include "path.h" | |
500ec543 ET |
14 | #include "pool.h" |
15 | #include "strmap.h" | |
f79026b4 VM |
16 | |
17 | /** | |
18 | * Filebuffer methods | |
19 | * | |
20 | * Read whole files into an in-memory buffer for processing | |
21 | */ | |
13224ea4 | 22 | extern int git_futils_readbuffer(git_buf *obj, const char *path); |
744cc03e RB |
23 | extern int git_futils_readbuffer_updated( |
24 | git_buf *obj, const char *path, time_t *mtime, size_t *size, int *updated); | |
60b9d3fc | 25 | extern int git_futils_readbuffer_fd(git_buf *obj, git_file fd, size_t len); |
f79026b4 | 26 | |
4742148d RB |
27 | extern int git_futils_writebuffer( |
28 | const git_buf *buf, const char *path, int open_flags, mode_t mode); | |
29 | ||
f79026b4 VM |
30 | /** |
31 | * File utils | |
32 | * | |
33 | * These are custom filesystem-related helper methods. They are | |
34 | * rather high level, and wrap the underlying POSIX methods | |
35 | * | |
0d0fa7c3 | 36 | * All these methods return 0 on success, |
f79026b4 VM |
37 | * or an error code on failure and an error message is set. |
38 | */ | |
39 | ||
f79026b4 VM |
40 | /** |
41 | * Create and open a file, while also | |
42 | * creating all the folders in its path | |
43 | */ | |
ce8cd006 | 44 | extern int git_futils_creat_withpath(const char *path, const mode_t dirmode, const mode_t mode); |
f79026b4 VM |
45 | |
46 | /** | |
47 | * Create an open a process-locked file | |
48 | */ | |
33127043 | 49 | extern int git_futils_creat_locked(const char *path, const mode_t mode); |
f79026b4 VM |
50 | |
51 | /** | |
52 | * Create an open a process-locked file, while | |
53 | * also creating all the folders in its path | |
54 | */ | |
ce8cd006 | 55 | extern int git_futils_creat_locked_withpath(const char *path, const mode_t dirmode, const mode_t mode); |
f79026b4 | 56 | |
662880ca | 57 | /** |
ca1b6e54 RB |
58 | * Create a path recursively |
59 | * | |
60 | * If a base parameter is being passed, it's expected to be valued with a | |
61 | * path pointing to an already existing directory. | |
662880ca | 62 | */ |
ca1b6e54 | 63 | extern int git_futils_mkdir_r(const char *path, const char *base, const mode_t mode); |
662880ca | 64 | |
f79026b4 | 65 | /** |
ca1b6e54 | 66 | * Flags to pass to `git_futils_mkdir`. |
dc07184f | 67 | * |
ca1b6e54 RB |
68 | * * GIT_MKDIR_EXCL is "exclusive" - i.e. generate an error if dir exists. |
69 | * * GIT_MKDIR_PATH says to make all components in the path. | |
70 | * * GIT_MKDIR_CHMOD says to chmod the final directory entry after creation | |
71 | * * GIT_MKDIR_CHMOD_PATH says to chmod each directory component in the path | |
72 | * * GIT_MKDIR_SKIP_LAST says to leave off the last element of the path | |
3c42e4ef | 73 | * * GIT_MKDIR_SKIP_LAST2 says to leave off the last 2 elements of the path |
331e7de9 | 74 | * * GIT_MKDIR_VERIFY_DIR says confirm final item is a dir, not just EEXIST |
e74340b0 ET |
75 | * * GIT_MKDIR_REMOVE_FILES says to remove files and recreate dirs |
76 | * * GIT_MKDIR_REMOVE_SYMLINKS says to remove symlinks and recreate dirs | |
ca1b6e54 RB |
77 | * |
78 | * Note that the chmod options will be executed even if the directory already | |
79 | * exists, unless GIT_MKDIR_EXCL is given. | |
f79026b4 | 80 | */ |
ca1b6e54 RB |
81 | typedef enum { |
82 | GIT_MKDIR_EXCL = 1, | |
83 | GIT_MKDIR_PATH = 2, | |
84 | GIT_MKDIR_CHMOD = 4, | |
85 | GIT_MKDIR_CHMOD_PATH = 8, | |
331e7de9 | 86 | GIT_MKDIR_SKIP_LAST = 16, |
3c42e4ef RB |
87 | GIT_MKDIR_SKIP_LAST2 = 32, |
88 | GIT_MKDIR_VERIFY_DIR = 64, | |
e74340b0 ET |
89 | GIT_MKDIR_REMOVE_FILES = 128, |
90 | GIT_MKDIR_REMOVE_SYMLINKS = 256, | |
ca1b6e54 RB |
91 | } git_futils_mkdir_flags; |
92 | ||
1d50b364 ET |
93 | struct git_futils_mkdir_perfdata |
94 | { | |
95 | size_t stat_calls; | |
96 | size_t mkdir_calls; | |
97 | size_t chmod_calls; | |
98 | }; | |
99 | ||
500ec543 ET |
100 | struct git_futils_mkdir_options |
101 | { | |
102 | git_strmap *dir_map; | |
103 | git_pool *pool; | |
104 | struct git_futils_mkdir_perfdata perfdata; | |
105 | }; | |
106 | ||
ca1b6e54 RB |
107 | /** |
108 | * Create a directory or entire path. | |
109 | * | |
110 | * This makes a directory (and the entire path leading up to it if requested), | |
111 | * and optionally chmods the directory immediately after (or each part of the | |
112 | * path if requested). | |
113 | * | |
114 | * @param path The path to create. | |
115 | * @param base Root for relative path. These directories will never be made. | |
116 | * @param mode The mode to use for created directories. | |
117 | * @param flags Combination of the mkdir flags above. | |
500ec543 | 118 | * @param opts Extended options, use `git_futils_mkdir` if you are not interested. |
ca1b6e54 RB |
119 | * @return 0 on success, else error code |
120 | */ | |
500ec543 | 121 | extern int git_futils_mkdir_ext(const char *path, const char *base, mode_t mode, uint32_t flags, struct git_futils_mkdir_options *opts); |
1d50b364 ET |
122 | |
123 | /** | |
124 | * Create a directory or entire path. Similar to `git_futils_mkdir_withperf` | |
125 | * without performance data. | |
126 | */ | |
ca1b6e54 | 127 | extern int git_futils_mkdir(const char *path, const char *base, mode_t mode, uint32_t flags); |
f79026b4 VM |
128 | |
129 | /** | |
130 | * Create all the folders required to contain | |
131 | * the full path of a file | |
132 | */ | |
ce8cd006 | 133 | extern int git_futils_mkpath2file(const char *path, const mode_t mode); |
f79026b4 | 134 | |
331e7de9 RB |
135 | /** |
136 | * Flags to pass to `git_futils_rmdir_r`. | |
137 | * | |
138 | * * GIT_RMDIR_EMPTY_HIERARCHY - the default; remove hierarchy of empty | |
139 | * dirs and generate error if any files are found. | |
140 | * * GIT_RMDIR_REMOVE_FILES - attempt to remove files in the hierarchy. | |
141 | * * GIT_RMDIR_SKIP_NONEMPTY - skip non-empty directories with no error. | |
142 | * * GIT_RMDIR_EMPTY_PARENTS - remove containing directories up to base | |
143 | * if removing this item leaves them empty | |
ad9a921b | 144 | * * GIT_RMDIR_REMOVE_BLOCKERS - remove blocking file that causes ENOTDIR |
219d3457 | 145 | * * GIT_RMDIR_SKIP_ROOT - don't remove root directory itself |
331e7de9 | 146 | */ |
555aa453 | 147 | typedef enum { |
331e7de9 RB |
148 | GIT_RMDIR_EMPTY_HIERARCHY = 0, |
149 | GIT_RMDIR_REMOVE_FILES = (1 << 0), | |
150 | GIT_RMDIR_SKIP_NONEMPTY = (1 << 1), | |
151 | GIT_RMDIR_EMPTY_PARENTS = (1 << 2), | |
ad9a921b | 152 | GIT_RMDIR_REMOVE_BLOCKERS = (1 << 3), |
219d3457 | 153 | GIT_RMDIR_SKIP_ROOT = (1 << 4), |
331e7de9 | 154 | } git_futils_rmdir_flags; |
555aa453 | 155 | |
df743c7d | 156 | /** |
1744fafe | 157 | * Remove path and any files and directories beneath it. |
555aa453 | 158 | * |
926acbcf | 159 | * @param path Path to the top level directory to process. |
0d64bef9 | 160 | * @param base Root for relative path. |
331e7de9 | 161 | * @param flags Combination of git_futils_rmdir_flags values |
555aa453 | 162 | * @return 0 on success; -1 on error. |
df743c7d | 163 | */ |
331e7de9 | 164 | extern int git_futils_rmdir_r(const char *path, const char *base, uint32_t flags); |
df743c7d | 165 | |
f79026b4 | 166 | /** |
97769280 RB |
167 | * Create and open a temporary file with a `_git2_` suffix. |
168 | * Writes the filename into path_out. | |
169 | * @return On success, an open file descriptor, else an error code < 0. | |
f79026b4 | 170 | */ |
1d3a8aeb | 171 | extern int git_futils_mktmp(git_buf *path_out, const char *filename, mode_t mode); |
f79026b4 | 172 | |
f79026b4 VM |
173 | /** |
174 | * Move a file on the filesystem, create the | |
175 | * destination path if it doesn't exist | |
176 | */ | |
ce8cd006 | 177 | extern int git_futils_mv_withpath(const char *from, const char *to, const mode_t dirmode); |
f79026b4 | 178 | |
ca1b6e54 | 179 | /** |
85bd1746 | 180 | * Copy a file |
ca1b6e54 | 181 | * |
85bd1746 | 182 | * The filemode will be used for the newly created file. |
ca1b6e54 | 183 | */ |
85bd1746 | 184 | extern int git_futils_cp( |
ca1b6e54 RB |
185 | const char *from, |
186 | const char *to, | |
85bd1746 | 187 | mode_t filemode); |
ca1b6e54 RB |
188 | |
189 | /** | |
190 | * Flags that can be passed to `git_futils_cp_r`. | |
18f08264 RB |
191 | * |
192 | * - GIT_CPDIR_CREATE_EMPTY_DIRS: create directories even if there are no | |
193 | * files under them (otherwise directories will only be created lazily | |
194 | * when a file inside them is copied). | |
195 | * - GIT_CPDIR_COPY_SYMLINKS: copy symlinks, otherwise they are ignored. | |
196 | * - GIT_CPDIR_COPY_DOTFILES: copy files with leading '.', otherwise ignored. | |
197 | * - GIT_CPDIR_OVERWRITE: overwrite pre-existing files with source content, | |
198 | * otherwise they are silently skipped. | |
199 | * - GIT_CPDIR_CHMOD_DIRS: explicitly chmod directories to `dirmode` | |
200 | * - GIT_CPDIR_SIMPLE_TO_MODE: default tries to replicate the mode of the | |
201 | * source file to the target; with this flag, always use 0666 (or 0777 if | |
202 | * source has exec bits set) for target. | |
94f742ba | 203 | * - GIT_CPDIR_LINK_FILES will try to use hardlinks for the files |
ca1b6e54 RB |
204 | */ |
205 | typedef enum { | |
3c42e4ef RB |
206 | GIT_CPDIR_CREATE_EMPTY_DIRS = (1u << 0), |
207 | GIT_CPDIR_COPY_SYMLINKS = (1u << 1), | |
208 | GIT_CPDIR_COPY_DOTFILES = (1u << 2), | |
209 | GIT_CPDIR_OVERWRITE = (1u << 3), | |
18f08264 RB |
210 | GIT_CPDIR_CHMOD_DIRS = (1u << 4), |
211 | GIT_CPDIR_SIMPLE_TO_MODE = (1u << 5), | |
94f742ba | 212 | GIT_CPDIR_LINK_FILES = (1u << 6), |
ca1b6e54 RB |
213 | } git_futils_cpdir_flags; |
214 | ||
215 | /** | |
216 | * Copy a directory tree. | |
217 | * | |
218 | * This copies directories and files from one root to another. You can | |
219 | * pass a combinationof GIT_CPDIR flags as defined above. | |
220 | * | |
221 | * If you pass the CHMOD flag, then the dirmode will be applied to all | |
222 | * directories that are created during the copy, overiding the natural | |
223 | * permissions. If you do not pass the CHMOD flag, then the dirmode | |
224 | * will actually be copied from the source files and the `dirmode` arg | |
225 | * will be ignored. | |
226 | */ | |
227 | extern int git_futils_cp_r( | |
228 | const char *from, | |
229 | const char *to, | |
230 | uint32_t flags, | |
231 | mode_t dirmode); | |
232 | ||
ae9e29fd | 233 | /** |
deafee7b | 234 | * Open a file readonly and set error if needed. |
ae9e29fd | 235 | */ |
deafee7b | 236 | extern int git_futils_open_ro(const char *path); |
ae9e29fd | 237 | |
f79026b4 VM |
238 | /** |
239 | * Get the filesize in bytes of a file | |
240 | */ | |
241 | extern git_off_t git_futils_filesize(git_file fd); | |
502acd16 | 242 | |
a7fcc44d RB |
243 | #define GIT_PERMS_IS_EXEC(MODE) (((MODE) & 0111) != 0) |
244 | #define GIT_PERMS_CANONICAL(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0755 : 0644) | |
245 | #define GIT_PERMS_FOR_WRITE(MODE) (GIT_PERMS_IS_EXEC(MODE) ? 0777 : 0666) | |
f240acce | 246 | |
74fa4bfa | 247 | #define GIT_MODE_PERMS_MASK 0777 |
af22dabb RB |
248 | #define GIT_MODE_TYPE_MASK 0170000 |
249 | #define GIT_MODE_TYPE(MODE) ((MODE) & GIT_MODE_TYPE_MASK) | |
9be5be47 | 250 | #define GIT_MODE_ISBLOB(MODE) (GIT_MODE_TYPE(MODE) == GIT_MODE_TYPE(GIT_FILEMODE_BLOB)) |
74fa4bfa | 251 | |
b6c93aef RB |
252 | /** |
253 | * Convert a mode_t from the OS to a legal git mode_t value. | |
254 | */ | |
255 | extern mode_t git_futils_canonical_mode(mode_t raw_mode); | |
256 | ||
257 | ||
20e7f426 SP |
258 | /** |
259 | * Read-only map all or part of a file into memory. | |
260 | * When possible this function should favor a virtual memory | |
261 | * style mapping over some form of malloc()+read(), as the | |
262 | * data access will be random and is not likely to touch the | |
263 | * majority of the region requested. | |
264 | * | |
265 | * @param out buffer to populate with the mapping information. | |
266 | * @param fd open descriptor to configure the mapping from. | |
267 | * @param begin first byte to map, this should be page aligned. | |
c05a55b0 | 268 | * @param len number of bytes to map. |
20e7f426 | 269 | * @return |
0d0fa7c3 RB |
270 | * - 0 on success; |
271 | * - -1 on error. | |
20e7f426 | 272 | */ |
f79026b4 | 273 | extern int git_futils_mmap_ro( |
79ca2edc | 274 | git_map *out, |
20e7f426 | 275 | git_file fd, |
f0bde7fa | 276 | git_off_t begin, |
20e7f426 SP |
277 | size_t len); |
278 | ||
74fa4bfa RB |
279 | /** |
280 | * Read-only map an entire file. | |
281 | * | |
282 | * @param out buffer to populate with the mapping information. | |
283 | * @param path path to file to be opened. | |
284 | * @return | |
0d0fa7c3 RB |
285 | * - 0 on success; |
286 | * - GIT_ENOTFOUND if not found; | |
287 | * - -1 on an unspecified OS related error. | |
74fa4bfa RB |
288 | */ |
289 | extern int git_futils_mmap_ro_file( | |
290 | git_map *out, | |
291 | const char *path); | |
292 | ||
20e7f426 SP |
293 | /** |
294 | * Release the memory associated with a previous memory mapping. | |
295 | * @param map the mapping description previously configured. | |
296 | */ | |
f79026b4 | 297 | extern void git_futils_mmap_free(git_map *map); |
20e7f426 | 298 | |
8651c10f BS |
299 | /** |
300 | * Create a "fake" symlink (text file containing the target path). | |
301 | * | |
302 | * @param new symlink file to be created | |
303 | * @param old original symlink target | |
304 | * @return 0 on success, -1 on error | |
305 | */ | |
306 | extern int git_futils_fake_symlink(const char *new, const char *old); | |
307 | ||
c8b511f3 RB |
308 | /** |
309 | * A file stamp represents a snapshot of information about a file that can | |
310 | * be used to test if the file changes. This portable implementation is | |
311 | * based on stat data about that file, but it is possible that OS specific | |
312 | * versions could be implemented in the future. | |
313 | */ | |
744cc03e | 314 | typedef struct { |
c8b511f3 | 315 | git_time_t mtime; |
744cc03e RB |
316 | git_off_t size; |
317 | unsigned int ino; | |
c1f61af6 | 318 | } git_futils_filestamp; |
744cc03e RB |
319 | |
320 | /** | |
321 | * Compare stat information for file with reference info. | |
322 | * | |
c8b511f3 | 323 | * This function updates the file stamp to current data for the given path |
7d490872 RB |
324 | * and returns 0 if the file is up-to-date relative to the prior setting, |
325 | * 1 if the file has been changed, or GIT_ENOTFOUND if the file doesn't | |
326 | * exist. This will not call giterr_set, so you must set the error if you | |
327 | * plan to return an error. | |
744cc03e | 328 | * |
c8b511f3 RB |
329 | * @param stamp File stamp to be checked |
330 | * @param path Path to stat and check if changed | |
7d490872 | 331 | * @return 0 if up-to-date, 1 if out-of-date, GIT_ENOTFOUND if cannot stat |
744cc03e | 332 | */ |
c1f61af6 VM |
333 | extern int git_futils_filestamp_check( |
334 | git_futils_filestamp *stamp, const char *path); | |
c8b511f3 RB |
335 | |
336 | /** | |
337 | * Set or reset file stamp data | |
338 | * | |
339 | * This writes the target file stamp. If the source is NULL, this will set | |
340 | * the target stamp to values that will definitely be out of date. If the | |
341 | * source is not NULL, this copies the source values to the target. | |
342 | * | |
343 | * @param tgt File stamp to write to | |
344 | * @param src File stamp to copy from or NULL to clear the target | |
345 | */ | |
c1f61af6 VM |
346 | extern void git_futils_filestamp_set( |
347 | git_futils_filestamp *tgt, const git_futils_filestamp *src); | |
744cc03e | 348 | |
823c0e9c RB |
349 | /** |
350 | * Set file stamp data from stat structure | |
351 | */ | |
352 | extern void git_futils_filestamp_set_from_stat( | |
353 | git_futils_filestamp *stamp, struct stat *st); | |
354 | ||
ec250c6e | 355 | #endif /* INCLUDE_fileops_h__ */ |