]>
Commit | Line | Data |
---|---|---|
bb742ede | 1 | /* |
359fc2d2 | 2 | * Copyright (C) the libgit2 contributors. All rights reserved. |
bb742ede VM |
3 | * |
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. | |
6 | */ | |
eae0bfdc | 7 | |
f79026b4 | 8 | #include "posix.h" |
eae0bfdc | 9 | |
f79026b4 VM |
10 | #include "path.h" |
11 | #include <stdio.h> | |
12 | #include <ctype.h> | |
13 | ||
e6ed0d2f ET |
14 | size_t p_fsync__cnt = 0; |
15 | ||
7998ae5a PB |
16 | #ifndef GIT_WIN32 |
17 | ||
798e4d53 | 18 | #ifdef NO_ADDRINFO |
71d62d39 | 19 | |
798e4d53 VM |
20 | int p_getaddrinfo( |
21 | const char *host, | |
22 | const char *port, | |
23 | struct addrinfo *hints, | |
24 | struct addrinfo **info) | |
25 | { | |
798e4d53 VM |
26 | struct addrinfo *ainfo, *ai; |
27 | int p = 0; | |
71d62d39 RB |
28 | |
29 | GIT_UNUSED(hints); | |
30 | ||
22a2d3d5 | 31 | if ((ainfo = git__malloc(sizeof(struct addrinfo))) == NULL) |
798e4d53 | 32 | return -1; |
71d62d39 RB |
33 | |
34 | if ((ainfo->ai_hostent = gethostbyname(host)) == NULL) { | |
22a2d3d5 | 35 | git__free(ainfo); |
798e4d53 | 36 | return -2; |
71d62d39 RB |
37 | } |
38 | ||
798e4d53 | 39 | ainfo->ai_servent = getservbyname(port, 0); |
71d62d39 | 40 | |
798e4d53 VM |
41 | if (ainfo->ai_servent) |
42 | ainfo->ai_port = ainfo->ai_servent->s_port; | |
43 | else | |
eae0bfdc | 44 | ainfo->ai_port = htons(atol(port)); |
798e4d53 VM |
45 | |
46 | memcpy(&ainfo->ai_addr_in.sin_addr, | |
47 | ainfo->ai_hostent->h_addr_list[0], | |
48 | ainfo->ai_hostent->h_length); | |
49 | ||
50 | ainfo->ai_protocol = 0; | |
51 | ainfo->ai_socktype = hints->ai_socktype; | |
52 | ainfo->ai_family = ainfo->ai_hostent->h_addrtype; | |
53 | ainfo->ai_addr_in.sin_family = ainfo->ai_family; | |
54 | ainfo->ai_addr_in.sin_port = ainfo->ai_port; | |
55 | ainfo->ai_addr = (struct addrinfo *)&ainfo->ai_addr_in; | |
56 | ainfo->ai_addrlen = sizeof(struct sockaddr_in); | |
57 | ||
58 | *info = ainfo; | |
71d62d39 | 59 | |
798e4d53 VM |
60 | if (ainfo->ai_hostent->h_addr_list[1] == NULL) { |
61 | ainfo->ai_next = NULL; | |
62 | return 0; | |
63 | } | |
71d62d39 | 64 | |
798e4d53 | 65 | ai = ainfo; |
71d62d39 | 66 | |
798e4d53 | 67 | for (p = 1; ainfo->ai_hostent->h_addr_list[p] != NULL; p++) { |
22a2d3d5 | 68 | if (!(ai->ai_next = git__malloc(sizeof(struct addrinfo)))) { |
ea5942b4 SB |
69 | p_freeaddrinfo(ainfo); |
70 | return -1; | |
71 | } | |
9f9df4b6 | 72 | memcpy(ai->ai_next, ainfo, sizeof(struct addrinfo)); |
798e4d53 VM |
73 | memcpy(&ai->ai_next->ai_addr_in.sin_addr, |
74 | ainfo->ai_hostent->h_addr_list[p], | |
75 | ainfo->ai_hostent->h_length); | |
76 | ai->ai_next->ai_addr = (struct addrinfo *)&ai->ai_next->ai_addr_in; | |
77 | ai = ai->ai_next; | |
78 | } | |
71d62d39 | 79 | |
798e4d53 VM |
80 | ai->ai_next = NULL; |
81 | return 0; | |
82 | } | |
83 | ||
84 | void p_freeaddrinfo(struct addrinfo *info) | |
85 | { | |
86 | struct addrinfo *p, *next; | |
71d62d39 | 87 | |
798e4d53 | 88 | p = info; |
71d62d39 | 89 | |
798e4d53 VM |
90 | while(p != NULL) { |
91 | next = p->ai_next; | |
22a2d3d5 | 92 | git__free(p); |
798e4d53 VM |
93 | p = next; |
94 | } | |
95 | } | |
96 | ||
97 | const char *p_gai_strerror(int ret) | |
98 | { | |
99 | switch(ret) { | |
71d62d39 RB |
100 | case -1: return "Out of memory"; break; |
101 | case -2: return "Address lookup failed"; break; | |
102 | default: return "Unknown error"; break; | |
798e4d53 VM |
103 | } |
104 | } | |
71d62d39 | 105 | |
798e4d53 VM |
106 | #endif /* NO_ADDRINFO */ |
107 | ||
6a1ca96e | 108 | int p_open(const char *path, volatile int flags, ...) |
f79026b4 | 109 | { |
3191ae89 | 110 | mode_t mode = 0; |
111 | ||
c25aa7cd PP |
112 | #ifdef GIT_DEBUG_STRICT_OPEN |
113 | if (strstr(path, "//") != NULL) { | |
114 | errno = EACCES; | |
115 | return -1; | |
116 | } | |
117 | #endif | |
118 | ||
71d62d39 | 119 | if (flags & O_CREAT) { |
3191ae89 | 120 | va_list arg_list; |
121 | ||
122 | va_start(arg_list, flags); | |
19579847 | 123 | mode = (mode_t)va_arg(arg_list, int); |
3191ae89 | 124 | va_end(arg_list); |
125 | } | |
126 | ||
3d3ea4dc | 127 | return open(path, flags | O_BINARY | O_CLOEXEC, mode); |
f79026b4 VM |
128 | } |
129 | ||
33127043 | 130 | int p_creat(const char *path, mode_t mode) |
f79026b4 | 131 | { |
3d3ea4dc | 132 | return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC, mode); |
f79026b4 VM |
133 | } |
134 | ||
7998ae5a PB |
135 | int p_getcwd(char *buffer_out, size_t size) |
136 | { | |
137 | char *cwd_buffer; | |
138 | ||
c25aa7cd PP |
139 | GIT_ASSERT_ARG(buffer_out); |
140 | GIT_ASSERT_ARG(size > 0); | |
7998ae5a PB |
141 | |
142 | cwd_buffer = getcwd(buffer_out, size); | |
143 | ||
144 | if (cwd_buffer == NULL) | |
dda708e7 | 145 | return -1; |
7998ae5a PB |
146 | |
147 | git_path_mkposix(buffer_out); | |
deafee7b | 148 | git_path_string_to_dir(buffer_out, size); /* append trailing slash */ |
97769280 | 149 | |
deafee7b | 150 | return 0; |
7998ae5a PB |
151 | } |
152 | ||
0c49ec2d CMN |
153 | int p_rename(const char *from, const char *to) |
154 | { | |
155 | if (!link(from, to)) { | |
156 | p_unlink(from); | |
dda708e7 | 157 | return 0; |
0c49ec2d CMN |
158 | } |
159 | ||
160 | if (!rename(from, to)) | |
dda708e7 | 161 | return 0; |
0c49ec2d | 162 | |
dda708e7 | 163 | return -1; |
0c49ec2d CMN |
164 | } |
165 | ||
798e4d53 | 166 | #endif /* GIT_WIN32 */ |
7998ae5a | 167 | |
c6ba8a37 | 168 | ssize_t p_read(git_file fd, void *buf, size_t cnt) |
f79026b4 VM |
169 | { |
170 | char *b = buf; | |
71d62d39 | 171 | |
8d534b47 ET |
172 | if (!git__is_ssizet(cnt)) { |
173 | #ifdef GIT_WIN32 | |
174 | SetLastError(ERROR_INVALID_PARAMETER); | |
175 | #endif | |
176 | errno = EINVAL; | |
177 | return -1; | |
178 | } | |
179 | ||
f79026b4 | 180 | while (cnt) { |
44ef8b1b RB |
181 | ssize_t r; |
182 | #ifdef GIT_WIN32 | |
c6ba8a37 | 183 | r = read(fd, b, cnt > INT_MAX ? INT_MAX : (unsigned int)cnt); |
44ef8b1b RB |
184 | #else |
185 | r = read(fd, b, cnt); | |
186 | #endif | |
f79026b4 VM |
187 | if (r < 0) { |
188 | if (errno == EINTR || errno == EAGAIN) | |
189 | continue; | |
dda708e7 | 190 | return -1; |
f79026b4 VM |
191 | } |
192 | if (!r) | |
193 | break; | |
194 | cnt -= r; | |
195 | b += r; | |
196 | } | |
c6ba8a37 | 197 | return (b - (char *)buf); |
f79026b4 VM |
198 | } |
199 | ||
2ba222c5 | 200 | int p_write(git_file fd, const void *buf, size_t cnt) |
f79026b4 | 201 | { |
2ba222c5 | 202 | const char *b = buf; |
71d62d39 | 203 | |
f79026b4 | 204 | while (cnt) { |
44ef8b1b RB |
205 | ssize_t r; |
206 | #ifdef GIT_WIN32 | |
c25aa7cd | 207 | GIT_ASSERT((size_t)((unsigned int)cnt) == cnt); |
44ef8b1b RB |
208 | r = write(fd, b, (unsigned int)cnt); |
209 | #else | |
210 | r = write(fd, b, cnt); | |
211 | #endif | |
f79026b4 | 212 | if (r < 0) { |
0197d410 | 213 | if (errno == EINTR || GIT_ISBLOCKED(errno)) |
f79026b4 | 214 | continue; |
dda708e7 | 215 | return -1; |
f79026b4 VM |
216 | } |
217 | if (!r) { | |
218 | errno = EPIPE; | |
dda708e7 | 219 | return -1; |
f79026b4 VM |
220 | } |
221 | cnt -= r; | |
222 | b += r; | |
223 | } | |
dda708e7 | 224 | return 0; |
f79026b4 | 225 | } |
345eef23 | 226 | |
7697e541 | 227 | #ifdef NO_MMAP |
345eef23 | 228 | |
7697e541 RB |
229 | #include "map.h" |
230 | ||
62e562f9 | 231 | int git__page_size(size_t *page_size) |
f7310540 CMN |
232 | { |
233 | /* dummy; here we don't need any alignment anyway */ | |
62e562f9 AM |
234 | *page_size = 4096; |
235 | return 0; | |
f7310540 CMN |
236 | } |
237 | ||
87c18197 CMN |
238 | int git__mmap_alignment(size_t *alignment) |
239 | { | |
240 | /* dummy; here we don't need any alignment anyway */ | |
241 | *alignment = 4096; | |
242 | return 0; | |
243 | } | |
244 | ||
f7310540 | 245 | |
22a2d3d5 | 246 | int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset) |
7697e541 | 247 | { |
c25aa7cd PP |
248 | const char *ptr; |
249 | size_t remaining_len; | |
250 | ||
7697e541 RB |
251 | GIT_MMAP_VALIDATE(out, len, prot, flags); |
252 | ||
c25aa7cd PP |
253 | /* writes cannot be emulated without handling pagefaults since write happens by |
254 | * writing to mapped memory */ | |
255 | if (prot & GIT_PROT_WRITE) { | |
256 | git_error_set(GIT_ERROR_OS, "trying to map %s-writeable", | |
257 | ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED) ? "shared": "private"); | |
258 | return -1; | |
259 | } | |
7697e541 | 260 | |
c25aa7cd PP |
261 | if (!git__is_ssizet(len)) { |
262 | errno = EINVAL; | |
7697e541 RB |
263 | return -1; |
264 | } | |
265 | ||
c25aa7cd | 266 | out->len = 0; |
22a2d3d5 | 267 | out->data = git__malloc(len); |
ac3d33df | 268 | GIT_ERROR_CHECK_ALLOC(out->data); |
7697e541 | 269 | |
c25aa7cd PP |
270 | remaining_len = len; |
271 | ptr = (const char *)out->data; | |
272 | while (remaining_len > 0) { | |
273 | ssize_t nb; | |
274 | HANDLE_EINTR(nb, p_pread(fd, (void *)ptr, remaining_len, offset)); | |
275 | if (nb <= 0) { | |
276 | git_error_set(GIT_ERROR_OS, "mmap emulation failed"); | |
277 | git__free(out->data); | |
278 | out->data = NULL; | |
279 | return -1; | |
280 | } | |
281 | ||
282 | ptr += nb; | |
283 | offset += nb; | |
284 | remaining_len -= nb; | |
7697e541 RB |
285 | } |
286 | ||
287 | out->len = len; | |
288 | return 0; | |
289 | } | |
290 | ||
291 | int p_munmap(git_map *map) | |
292 | { | |
c25aa7cd | 293 | GIT_ASSERT_ARG(map); |
22a2d3d5 | 294 | git__free(map->data); |
7697e541 | 295 | |
c25aa7cd PP |
296 | /* Initializing will help debug use-after-free */ |
297 | map->len = 0; | |
298 | map->data = NULL; | |
299 | ||
7697e541 RB |
300 | return 0; |
301 | } | |
302 | ||
303 | #endif |