]>
Commit | Line | Data |
---|---|---|
5ee2fe77 | 1 | #include "common.h" |
ec250c6e | 2 | #include "fileops.h" |
2e29957a | 3 | #include <ctype.h> |
ec250c6e | 4 | |
72a3fe42 | 5 | int gitfo_mkdir_2file(const char *file_path) |
55ffebe3 VM |
6 | { |
7 | const int mode = 0755; /* or 0777 ? */ | |
8 | int error = GIT_SUCCESS; | |
9 | char target_folder_path[GIT_PATH_MAX]; | |
10 | ||
72a3fe42 | 11 | error = git__dirname_r(target_folder_path, sizeof(target_folder_path), file_path); |
55ffebe3 VM |
12 | if (error < GIT_SUCCESS) |
13 | return error; | |
14 | ||
15 | /* Does the containing folder exist? */ | |
16 | if (gitfo_isdir(target_folder_path)) { | |
17 | git__joinpath(target_folder_path, target_folder_path, ""); /* Ensure there's a trailing slash */ | |
18 | ||
19 | /* Let's create the tree structure */ | |
20 | error = gitfo_mkdir_recurs(target_folder_path, mode); | |
21 | if (error < GIT_SUCCESS) | |
22 | return error; | |
23 | } | |
24 | ||
25 | return GIT_SUCCESS; | |
26 | } | |
27 | ||
f6f72d7e | 28 | int gitfo_mktemp(char *path_out, const char *filename) |
72a3fe42 VM |
29 | { |
30 | int fd; | |
31 | ||
f6f72d7e | 32 | strcpy(path_out, filename); |
72a3fe42 VM |
33 | strcat(path_out, "_git2_XXXXXX"); |
34 | ||
7c80c19e | 35 | #if defined(_MSC_VER) |
72a3fe42 VM |
36 | /* FIXME: there may be race conditions when multi-threading |
37 | * with the library */ | |
38 | if (_mktemp_s(path_out, GIT_PATH_MAX) != 0) | |
39 | return GIT_EOSERR; | |
40 | ||
41 | fd = gitfo_creat(path_out, 0744); | |
42 | #else | |
43 | fd = mkstemp(path_out); | |
44 | #endif | |
45 | ||
46 | return fd >= 0 ? fd : GIT_EOSERR; | |
47 | } | |
48 | ||
7dd8a9f7 SP |
49 | int gitfo_open(const char *path, int flags) |
50 | { | |
7a6cf815 | 51 | int fd = open(path, flags | O_BINARY); |
9f54fe48 | 52 | return fd >= 0 ? fd : GIT_EOSERR; |
7dd8a9f7 SP |
53 | } |
54 | ||
55 | int gitfo_creat(const char *path, int mode) | |
56 | { | |
7a6cf815 | 57 | int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); |
9f54fe48 | 58 | return fd >= 0 ? fd : GIT_EOSERR; |
7dd8a9f7 SP |
59 | } |
60 | ||
55ffebe3 VM |
61 | int gitfo_creat_force(const char *path, int mode) |
62 | { | |
72a3fe42 | 63 | if (gitfo_mkdir_2file(path) < GIT_SUCCESS) |
55ffebe3 VM |
64 | return GIT_EOSERR; |
65 | ||
66 | return gitfo_creat(path, mode); | |
67 | } | |
68 | ||
ec250c6e AE |
69 | int gitfo_read(git_file fd, void *buf, size_t cnt) |
70 | { | |
71 | char *b = buf; | |
72 | while (cnt) { | |
73 | ssize_t r = read(fd, b, cnt); | |
74 | if (r < 0) { | |
75 | if (errno == EINTR || errno == EAGAIN) | |
76 | continue; | |
9f54fe48 | 77 | return GIT_EOSERR; |
ec250c6e AE |
78 | } |
79 | if (!r) { | |
80 | errno = EPIPE; | |
9f54fe48 | 81 | return GIT_EOSERR; |
ec250c6e AE |
82 | } |
83 | cnt -= r; | |
84 | b += r; | |
85 | } | |
86 | return GIT_SUCCESS; | |
87 | } | |
88 | ||
89 | int gitfo_write(git_file fd, void *buf, size_t cnt) | |
90 | { | |
91 | char *b = buf; | |
92 | while (cnt) { | |
93 | ssize_t r = write(fd, b, cnt); | |
94 | if (r < 0) { | |
95 | if (errno == EINTR || errno == EAGAIN) | |
96 | continue; | |
9f54fe48 | 97 | return GIT_EOSERR; |
ec250c6e AE |
98 | } |
99 | if (!r) { | |
100 | errno = EPIPE; | |
9f54fe48 | 101 | return GIT_EOSERR; |
ec250c6e AE |
102 | } |
103 | cnt -= r; | |
104 | b += r; | |
105 | } | |
106 | return GIT_SUCCESS; | |
107 | } | |
108 | ||
6fd195d7 VM |
109 | int gitfo_isdir(const char *path) |
110 | { | |
111 | struct stat st; | |
43e380a8 VM |
112 | int len, stat_error; |
113 | ||
114 | if (!path) | |
115 | return GIT_ENOTFOUND; | |
116 | ||
117 | len = strlen(path); | |
118 | ||
119 | /* win32: stat path for folders cannot end in a slash */ | |
120 | if (path[len - 1] == '/') { | |
121 | char *path_fixed = NULL; | |
122 | path_fixed = git__strdup(path); | |
123 | path_fixed[len - 1] = 0; | |
124 | stat_error = gitfo_stat(path_fixed, &st); | |
125 | free(path_fixed); | |
126 | } else { | |
127 | stat_error = gitfo_stat(path, &st); | |
128 | } | |
129 | ||
1f080e2d VM |
130 | if (stat_error < GIT_SUCCESS) |
131 | return GIT_ENOTFOUND; | |
132 | ||
133 | if (!S_ISDIR(st.st_mode)) | |
134 | return GIT_ENOTFOUND; | |
135 | ||
136 | return GIT_SUCCESS; | |
6fd195d7 VM |
137 | } |
138 | ||
7350e633 SP |
139 | int gitfo_exists(const char *path) |
140 | { | |
72a3fe42 | 141 | assert(path); |
4d503f88 | 142 | return access(path, F_OK); |
7350e633 SP |
143 | } |
144 | ||
f0bde7fa | 145 | git_off_t gitfo_size(git_file fd) |
ec250c6e | 146 | { |
7dd8a9f7 | 147 | struct stat sb; |
3cc60635 | 148 | if (gitfo_fstat(fd, &sb)) |
9f54fe48 | 149 | return GIT_EOSERR; |
ec250c6e AE |
150 | return sb.st_size; |
151 | } | |
4188d28f | 152 | |
75d58430 RJ |
153 | int gitfo_read_file(gitfo_buf *obj, const char *path) |
154 | { | |
155 | git_file fd; | |
90d4d2f0 | 156 | size_t len; |
f0bde7fa | 157 | git_off_t size; |
42fd40db | 158 | unsigned char *buff; |
75d58430 RJ |
159 | |
160 | assert(obj && path && *path); | |
161 | ||
162 | if ((fd = gitfo_open(path, O_RDONLY)) < 0) | |
64a47c01 | 163 | return GIT_ERROR; |
75d58430 | 164 | |
90d4d2f0 RJ |
165 | if (((size = gitfo_size(fd)) < 0) || !git__is_sizet(size+1)) { |
166 | gitfo_close(fd); | |
167 | return GIT_ERROR; | |
168 | } | |
169 | len = (size_t) size; | |
170 | ||
171 | if ((buff = git__malloc(len + 1)) == NULL) { | |
75d58430 | 172 | gitfo_close(fd); |
64a47c01 | 173 | return GIT_ERROR; |
75d58430 RJ |
174 | } |
175 | ||
176 | if (gitfo_read(fd, buff, len) < 0) { | |
177 | gitfo_close(fd); | |
178 | free(buff); | |
64a47c01 | 179 | return GIT_ERROR; |
75d58430 | 180 | } |
42fd40db | 181 | buff[len] = '\0'; |
75d58430 RJ |
182 | |
183 | gitfo_close(fd); | |
184 | ||
185 | obj->data = buff; | |
186 | obj->len = len; | |
187 | ||
188 | return GIT_SUCCESS; | |
189 | } | |
190 | ||
191 | void gitfo_free_buf(gitfo_buf *obj) | |
192 | { | |
193 | assert(obj); | |
194 | free(obj->data); | |
195 | obj->data = NULL; | |
196 | } | |
197 | ||
19a30a3f | 198 | int gitfo_mv(const char *from, const char *to) |
ca481fc4 | 199 | { |
3eb47c9f VM |
200 | #ifdef GIT_WIN32 |
201 | /* | |
202 | * Win32 POSIX compilance my ass. If the destination | |
203 | * file exists, the `rename` call fails. This is as | |
204 | * close as it gets with the Win32 API. | |
205 | */ | |
ae6ba7f7 | 206 | return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? GIT_SUCCESS : GIT_EOSERR; |
3eb47c9f VM |
207 | #else |
208 | /* Don't even try this on Win32 */ | |
ca481fc4 RJ |
209 | if (!link(from, to)) { |
210 | gitfo_unlink(from); | |
211 | return GIT_SUCCESS; | |
212 | } | |
213 | ||
214 | if (!rename(from, to)) | |
215 | return GIT_SUCCESS; | |
216 | ||
9f54fe48 | 217 | return GIT_EOSERR; |
7360122b | 218 | #endif |
ca481fc4 RJ |
219 | } |
220 | ||
19a30a3f VM |
221 | int gitfo_mv_force(const char *from, const char *to) |
222 | { | |
72a3fe42 | 223 | if (gitfo_mkdir_2file(to) < GIT_SUCCESS) |
55ffebe3 | 224 | return GIT_EOSERR; |
19a30a3f VM |
225 | |
226 | return gitfo_mv(from, to); | |
227 | } | |
228 | ||
f0bde7fa | 229 | int gitfo_map_ro(git_map *out, git_file fd, git_off_t begin, size_t len) |
20e7f426 | 230 | { |
6f02c3ba | 231 | if (git__mmap(out, len, GIT_PROT_READ, GIT_MAP_SHARED, fd, begin) < GIT_SUCCESS) |
9f54fe48 | 232 | return GIT_EOSERR; |
20e7f426 SP |
233 | return GIT_SUCCESS; |
234 | } | |
235 | ||
79ca2edc | 236 | void gitfo_free_map(git_map *out) |
20e7f426 | 237 | { |
79ca2edc | 238 | git__munmap(out); |
20e7f426 SP |
239 | } |
240 | ||
4188d28f AE |
241 | /* cached diskio */ |
242 | struct gitfo_cache { | |
243 | git_file fd; | |
4c9a3973 | 244 | size_t cache_size, pos; |
fc3c3a20 | 245 | unsigned char *cache; |
4188d28f AE |
246 | }; |
247 | ||
248 | gitfo_cache *gitfo_enable_caching(git_file fd, size_t cache_size) | |
249 | { | |
250 | gitfo_cache *ioc; | |
251 | ||
64a47c01 | 252 | ioc = git__malloc(sizeof(*ioc)); |
4188d28f AE |
253 | if (!ioc) |
254 | return NULL; | |
255 | ||
803a6b4d | 256 | ioc->fd = fd; |
4188d28f AE |
257 | ioc->pos = 0; |
258 | ioc->cache_size = cache_size; | |
64a47c01 | 259 | ioc->cache = git__malloc(cache_size); |
4188d28f AE |
260 | if (!ioc->cache) { |
261 | free(ioc); | |
262 | return NULL; | |
263 | } | |
264 | ||
265 | return ioc; | |
266 | } | |
267 | ||
213e720c | 268 | GIT_INLINE(void) gitfo_add_to_cache(gitfo_cache *ioc, void *buf, size_t len) |
4188d28f AE |
269 | { |
270 | memcpy(ioc->cache + ioc->pos, buf, len); | |
271 | ioc->pos += len; | |
272 | } | |
273 | ||
274 | int gitfo_flush_cached(gitfo_cache *ioc) | |
275 | { | |
276 | int result = GIT_SUCCESS; | |
277 | ||
278 | if (ioc->pos) { | |
279 | result = gitfo_write(ioc->fd, ioc->cache, ioc->pos); | |
280 | ioc->pos = 0; | |
281 | } | |
282 | ||
283 | return result; | |
284 | } | |
285 | ||
fc3c3a20 | 286 | int gitfo_write_cached(gitfo_cache *ioc, void *buff, size_t len) |
4188d28f | 287 | { |
fc3c3a20 RJ |
288 | unsigned char *buf = buff; |
289 | ||
4188d28f AE |
290 | for (;;) { |
291 | size_t space_left = ioc->cache_size - ioc->pos; | |
292 | /* cache if it's small */ | |
293 | if (space_left > len) { | |
294 | gitfo_add_to_cache(ioc, buf, len); | |
295 | return GIT_SUCCESS; | |
296 | } | |
297 | ||
298 | /* flush the cache if it doesn't fit */ | |
299 | if (ioc->pos) { | |
300 | int rc; | |
301 | gitfo_add_to_cache(ioc, buf, space_left); | |
302 | rc = gitfo_flush_cached(ioc); | |
303 | if (rc < 0) | |
304 | return rc; | |
305 | ||
306 | len -= space_left; | |
307 | buf += space_left; | |
308 | } | |
309 | ||
310 | /* write too-large chunks immediately */ | |
311 | if (len > ioc->cache_size) | |
312 | return gitfo_write(ioc->fd, buf, len); | |
313 | } | |
4188d28f AE |
314 | } |
315 | ||
316 | int gitfo_close_cached(gitfo_cache *ioc) | |
317 | { | |
318 | git_file fd; | |
319 | ||
6f02c3ba | 320 | if (gitfo_flush_cached(ioc) < GIT_SUCCESS) |
7dd8a9f7 | 321 | return GIT_ERROR; |
4188d28f AE |
322 | |
323 | fd = ioc->fd; | |
324 | free(ioc->cache); | |
325 | free(ioc); | |
326 | ||
327 | return gitfo_close(fd); | |
328 | } | |
ea790f33 | 329 | |
5690f02e SP |
330 | int gitfo_dirent( |
331 | char *path, | |
332 | size_t path_sz, | |
333 | int (*fn)(void *, char *), | |
334 | void *arg) | |
ea790f33 | 335 | { |
5690f02e | 336 | size_t wd_len = strlen(path); |
ea790f33 AE |
337 | DIR *dir; |
338 | struct dirent *de; | |
339 | ||
5690f02e | 340 | if (!wd_len || path_sz < wd_len + 2) |
ea790f33 AE |
341 | return GIT_ERROR; |
342 | ||
ea790f33 AE |
343 | while (path[wd_len - 1] == '/') |
344 | wd_len--; | |
345 | path[wd_len++] = '/'; | |
346 | path[wd_len] = '\0'; | |
347 | ||
5690f02e | 348 | dir = opendir(path); |
ea790f33 | 349 | if (!dir) |
9f54fe48 | 350 | return GIT_EOSERR; |
ea790f33 | 351 | |
a9984a4e | 352 | while ((de = readdir(dir)) != NULL) { |
ea790f33 AE |
353 | size_t de_len; |
354 | int result; | |
355 | ||
356 | /* always skip '.' and '..' */ | |
357 | if (de->d_name[0] == '.') { | |
358 | if (de->d_name[1] == '\0') | |
359 | continue; | |
360 | if (de->d_name[1] == '.' && de->d_name[2] == '\0') | |
361 | continue; | |
362 | } | |
363 | ||
364 | de_len = strlen(de->d_name); | |
5690f02e | 365 | if (path_sz < wd_len + de_len + 1) { |
ea790f33 AE |
366 | closedir(dir); |
367 | return GIT_ERROR; | |
368 | } | |
369 | ||
370 | strcpy(path + wd_len, de->d_name); | |
371 | result = fn(arg, path); | |
6f02c3ba | 372 | if (result < GIT_SUCCESS) { |
ea790f33 AE |
373 | closedir(dir); |
374 | return result; | |
375 | } | |
376 | if (result > 0) { | |
377 | closedir(dir); | |
378 | return result; | |
379 | } | |
380 | } | |
381 | ||
382 | closedir(dir); | |
383 | return GIT_SUCCESS; | |
384 | } | |
1a5204a7 | 385 | |
23a1edbd | 386 | |
c90292ce | 387 | int retrieve_path_root_offset(const char *path) |
23a1edbd | 388 | { |
c90292ce | 389 | int offset = 0; |
390 | ||
391 | #ifdef GIT_WIN32 | |
392 | ||
23a1edbd | 393 | /* Does the root of the path look like a windows drive ? */ |
2c08c3f0 | 394 | if (isalpha(path[0]) && (path[1] == ':')) |
c90292ce | 395 | offset += 2; |
396 | ||
397 | #endif | |
398 | ||
399 | if (*(path + offset) == '/') | |
400 | return offset; | |
23a1edbd | 401 | |
402 | return GIT_ERROR; | |
403 | } | |
404 | ||
23a1edbd | 405 | |
1a5204a7 | 406 | int gitfo_mkdir_recurs(const char *path, int mode) |
407 | { | |
c90292ce | 408 | int error, root_path_offset; |
40c44d2f VM |
409 | char *pp, *sp; |
410 | char *path_copy = git__strdup(path); | |
f0b2bfe5 | 411 | |
40c44d2f VM |
412 | if (path_copy == NULL) |
413 | return GIT_ENOMEM; | |
f0b2bfe5 | 414 | |
d5f25204 VM |
415 | error = GIT_SUCCESS; |
416 | pp = path_copy; | |
40c44d2f | 417 | |
c90292ce | 418 | root_path_offset = retrieve_path_root_offset(pp); |
419 | if (root_path_offset > 0) | |
420 | pp += root_path_offset; /* On Windows, will skip the drive name (eg. C: or D:) */ | |
2e29957a | 421 | |
412de9a6 | 422 | while (error == GIT_SUCCESS && (sp = strchr(pp, '/')) != 0) { |
d5f25204 VM |
423 | if (sp != pp && gitfo_isdir(path_copy) < GIT_SUCCESS) { |
424 | *sp = 0; | |
425 | error = gitfo_mkdir(path_copy, mode); | |
412de9a6 | 426 | |
427 | /* Do not choke while trying to recreate an existing directory */ | |
428 | if (errno == EEXIST) | |
429 | error = GIT_SUCCESS; | |
430 | ||
d5f25204 VM |
431 | *sp = '/'; |
432 | } | |
40c44d2f | 433 | |
d5f25204 VM |
434 | pp = sp + 1; |
435 | } | |
f0b2bfe5 | 436 | |
d5f25204 VM |
437 | if (*(pp - 1) != '/' && error == GIT_SUCCESS) |
438 | error = gitfo_mkdir(path, mode); | |
40c44d2f | 439 | |
d5f25204 VM |
440 | free(path_copy); |
441 | return error; | |
170d3f2f | 442 | } |
443 | ||
444 | static int retrieve_previous_path_component_start(const char *path) | |
445 | { | |
3644e98f | 446 | int offset, len, root_offset, start = 0; |
447 | ||
448 | root_offset = retrieve_path_root_offset(path); | |
449 | if (root_offset > -1) | |
450 | start += root_offset; | |
451 | ||
170d3f2f | 452 | len = strlen(path); |
453 | offset = len - 1; | |
40c44d2f | 454 | |
170d3f2f | 455 | /* Skip leading slash */ |
456 | if (path[start] == '/') | |
457 | start++; | |
458 | ||
459 | /* Skip trailing slash */ | |
460 | if (path[offset] == '/') | |
461 | offset--; | |
462 | ||
3644e98f | 463 | if (offset < root_offset) |
170d3f2f | 464 | return GIT_ERROR; |
465 | ||
466 | while (offset > start && path[offset-1] != '/') { | |
467 | offset--; | |
468 | } | |
469 | ||
470 | return offset; | |
40c44d2f | 471 | } |
170d3f2f | 472 | |
c90292ce | 473 | int gitfo_prettify_dir_path(char *buffer_out, size_t size, const char *path) |
170d3f2f | 474 | { |
c90292ce | 475 | int len = 0, segment_len, only_dots, root_path_offset, error = GIT_SUCCESS; |
4581c22a | 476 | char *current; |
170d3f2f | 477 | const char *buffer_out_start, *buffer_end; |
478 | ||
170d3f2f | 479 | current = (char *)path; |
480 | buffer_end = path + strlen(path); | |
c90292ce | 481 | buffer_out_start = buffer_out; |
482 | ||
483 | root_path_offset = retrieve_path_root_offset(path); | |
484 | if (root_path_offset < 0) { | |
485 | error = gitfo_getcwd(buffer_out, size); | |
486 | if (error < GIT_SUCCESS) | |
487 | return error; | |
488 | ||
489 | len = strlen(buffer_out); | |
490 | buffer_out += len; | |
491 | } | |
170d3f2f | 492 | |
493 | while (current < buffer_end) { | |
494 | /* Prevent multiple slashes from being added to the output */ | |
495 | if (*current == '/' && len > 0 && buffer_out_start[len - 1] == '/') { | |
496 | current++; | |
497 | continue; | |
498 | } | |
499 | ||
ae7ffea9 | 500 | only_dots = 1; |
4581c22a | 501 | segment_len = 0; |
ae7ffea9 | 502 | |
4581c22a | 503 | /* Copy path segment to the output */ |
c90292ce | 504 | while (current < buffer_end && *current != '/') |
ae7ffea9 | 505 | { |
4581c22a | 506 | only_dots &= (*current == '.'); |
507 | *buffer_out++ = *current++; | |
508 | segment_len++; | |
509 | len++; | |
ae7ffea9 | 510 | } |
e16c2f6a | 511 | |
ae7ffea9 | 512 | /* Skip current directory */ |
4581c22a | 513 | if (only_dots && segment_len == 1) |
ae7ffea9 | 514 | { |
4581c22a | 515 | current++; |
516 | buffer_out -= segment_len; | |
517 | len -= segment_len; | |
ae7ffea9 | 518 | continue; |
519 | } | |
40c44d2f | 520 | |
ae7ffea9 | 521 | /* Handle the double-dot upward directory navigation */ |
4581c22a | 522 | if (only_dots && segment_len == 2) |
ae7ffea9 | 523 | { |
4581c22a | 524 | current++; |
525 | buffer_out -= segment_len; | |
526 | ||
ae7ffea9 | 527 | *buffer_out ='\0'; |
528 | len = retrieve_previous_path_component_start(buffer_out_start); | |
c90292ce | 529 | |
530 | /* Are we escaping out of the root dir? */ | |
531 | if (len < 0) | |
f2c24713 | 532 | return GIT_EINVALIDPATH; |
ae7ffea9 | 533 | |
534 | buffer_out = (char *)buffer_out_start + len; | |
ae7ffea9 | 535 | continue; |
536 | } | |
170d3f2f | 537 | |
ae7ffea9 | 538 | /* Guard against potential multiple dot path traversal (cf http://cwe.mitre.org/data/definitions/33.html) */ |
c90292ce | 539 | if (only_dots && segment_len > 0) |
f2c24713 | 540 | return GIT_EINVALIDPATH; |
170d3f2f | 541 | |
ae7ffea9 | 542 | *buffer_out++ = '/'; |
170d3f2f | 543 | len++; |
544 | } | |
545 | ||
170d3f2f | 546 | *buffer_out = '\0'; |
547 | ||
548 | return GIT_SUCCESS; | |
40c44d2f | 549 | } |
618818dc | 550 | |
c90292ce | 551 | int gitfo_prettify_file_path(char *buffer_out, size_t size, const char *path) |
618818dc | 552 | { |
553 | int error, path_len, i; | |
554 | const char* pattern = "/.."; | |
555 | ||
556 | path_len = strlen(path); | |
557 | ||
c90292ce | 558 | /* Let's make sure the filename isn't empty nor a dot */ |
559 | if (path_len == 0 || (path_len == 1 && *path == '.')) | |
560 | return GIT_EINVALIDPATH; | |
561 | ||
618818dc | 562 | /* Let's make sure the filename doesn't end with "/", "/." or "/.." */ |
563 | for (i = 1; path_len > i && i < 4; i++) { | |
564 | if (!strncmp(path + path_len - i, pattern, i)) | |
f2c24713 | 565 | return GIT_EINVALIDPATH; |
618818dc | 566 | } |
567 | ||
c90292ce | 568 | error = gitfo_prettify_dir_path(buffer_out, size, path); |
618818dc | 569 | if (error < GIT_SUCCESS) |
570 | return error; | |
571 | ||
572 | path_len = strlen(buffer_out); | |
573 | if (path_len < 2) | |
f2c24713 | 574 | return GIT_EINVALIDPATH; |
618818dc | 575 | |
576 | /* Remove the trailing slash */ | |
577 | buffer_out[path_len - 1] = '\0'; | |
578 | ||
579 | return GIT_SUCCESS; | |
580 | } | |
ccef1c9d VM |
581 | |
582 | int gitfo_cmp_path(const char *name1, int len1, int isdir1, | |
583 | const char *name2, int len2, int isdir2) | |
584 | { | |
585 | int len = len1 < len2 ? len1 : len2; | |
586 | int cmp; | |
587 | ||
588 | cmp = memcmp(name1, name2, len); | |
589 | if (cmp) | |
590 | return cmp; | |
591 | if (len1 < len2) | |
592 | return ((!isdir1 && !isdir2) ? -1 : | |
593 | (isdir1 ? '/' - name2[len1] : name2[len1] - '/')); | |
594 | if (len1 > len2) | |
595 | return ((!isdir1 && !isdir2) ? 1 : | |
596 | (isdir2 ? name1[len2] - '/' : '/' - name1[len2])); | |
597 | return 0; | |
598 | } | |
599 | ||
677a3c07 | 600 | static void posixify_path(char *path) |
601 | { | |
602 | while (*path) { | |
603 | if (*path == '\\') | |
604 | *path = '/'; | |
605 | ||
606 | path++; | |
607 | } | |
608 | } | |
609 | ||
610 | int gitfo_getcwd(char *buffer_out, size_t size) | |
611 | { | |
612 | char *cwd_buffer; | |
613 | ||
614 | assert(buffer_out && size > 0); | |
615 | ||
616 | #ifdef GIT_WIN32 | |
617 | cwd_buffer = _getcwd(buffer_out, size); | |
618 | #else | |
619 | cwd_buffer = getcwd(buffer_out, size); //TODO: Fixme. Ensure the required headers are correctly included | |
620 | #endif | |
621 | ||
622 | if (cwd_buffer == NULL) | |
623 | return GIT_EOSERR; | |
624 | ||
625 | posixify_path(buffer_out); | |
626 | ||
627 | git__joinpath(buffer_out, buffer_out, ""); //Ensure the path ends with a trailing slash | |
628 | ||
629 | return GIT_SUCCESS; | |
630 | } |