]> git.proxmox.com Git - libgit2.git/blob - src/posix.c
New upstream version 1.4.3+dfsg.1
[libgit2.git] / src / posix.c
1 /*
2 * Copyright (C) the libgit2 contributors. All rights reserved.
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 */
7
8 #include "posix.h"
9
10 #include "fs_path.h"
11 #include <stdio.h>
12 #include <ctype.h>
13
14 size_t p_fsync__cnt = 0;
15
16 #ifndef GIT_WIN32
17
18 #ifdef NO_ADDRINFO
19
20 int p_getaddrinfo(
21 const char *host,
22 const char *port,
23 struct addrinfo *hints,
24 struct addrinfo **info)
25 {
26 struct addrinfo *ainfo, *ai;
27 int p = 0;
28
29 GIT_UNUSED(hints);
30
31 if ((ainfo = git__malloc(sizeof(struct addrinfo))) == NULL)
32 return -1;
33
34 if ((ainfo->ai_hostent = gethostbyname(host)) == NULL) {
35 git__free(ainfo);
36 return -2;
37 }
38
39 ainfo->ai_servent = getservbyname(port, 0);
40
41 if (ainfo->ai_servent)
42 ainfo->ai_port = ainfo->ai_servent->s_port;
43 else
44 ainfo->ai_port = htons(atol(port));
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;
59
60 if (ainfo->ai_hostent->h_addr_list[1] == NULL) {
61 ainfo->ai_next = NULL;
62 return 0;
63 }
64
65 ai = ainfo;
66
67 for (p = 1; ainfo->ai_hostent->h_addr_list[p] != NULL; p++) {
68 if (!(ai->ai_next = git__malloc(sizeof(struct addrinfo)))) {
69 p_freeaddrinfo(ainfo);
70 return -1;
71 }
72 memcpy(ai->ai_next, ainfo, sizeof(struct addrinfo));
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 }
79
80 ai->ai_next = NULL;
81 return 0;
82 }
83
84 void p_freeaddrinfo(struct addrinfo *info)
85 {
86 struct addrinfo *p, *next;
87
88 p = info;
89
90 while(p != NULL) {
91 next = p->ai_next;
92 git__free(p);
93 p = next;
94 }
95 }
96
97 const char *p_gai_strerror(int ret)
98 {
99 switch(ret) {
100 case -1: return "Out of memory"; break;
101 case -2: return "Address lookup failed"; break;
102 default: return "Unknown error"; break;
103 }
104 }
105
106 #endif /* NO_ADDRINFO */
107
108 int p_open(const char *path, volatile int flags, ...)
109 {
110 mode_t mode = 0;
111
112 #ifdef GIT_DEBUG_STRICT_OPEN
113 if (strstr(path, "//") != NULL) {
114 errno = EACCES;
115 return -1;
116 }
117 #endif
118
119 if (flags & O_CREAT) {
120 va_list arg_list;
121
122 va_start(arg_list, flags);
123 mode = (mode_t)va_arg(arg_list, int);
124 va_end(arg_list);
125 }
126
127 return open(path, flags | O_BINARY | O_CLOEXEC, mode);
128 }
129
130 int p_creat(const char *path, mode_t mode)
131 {
132 return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC, mode);
133 }
134
135 int p_getcwd(char *buffer_out, size_t size)
136 {
137 char *cwd_buffer;
138
139 GIT_ASSERT_ARG(buffer_out);
140 GIT_ASSERT_ARG(size > 0);
141
142 cwd_buffer = getcwd(buffer_out, size);
143
144 if (cwd_buffer == NULL)
145 return -1;
146
147 git_fs_path_mkposix(buffer_out);
148 git_fs_path_string_to_dir(buffer_out, size); /* append trailing slash */
149
150 return 0;
151 }
152
153 int p_rename(const char *from, const char *to)
154 {
155 if (!link(from, to)) {
156 p_unlink(from);
157 return 0;
158 }
159
160 if (!rename(from, to))
161 return 0;
162
163 return -1;
164 }
165
166 #endif /* GIT_WIN32 */
167
168 ssize_t p_read(git_file fd, void *buf, size_t cnt)
169 {
170 char *b = buf;
171
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
180 while (cnt) {
181 ssize_t r;
182 #ifdef GIT_WIN32
183 r = read(fd, b, cnt > INT_MAX ? INT_MAX : (unsigned int)cnt);
184 #else
185 r = read(fd, b, cnt);
186 #endif
187 if (r < 0) {
188 if (errno == EINTR || errno == EAGAIN)
189 continue;
190 return -1;
191 }
192 if (!r)
193 break;
194 cnt -= r;
195 b += r;
196 }
197 return (b - (char *)buf);
198 }
199
200 int p_write(git_file fd, const void *buf, size_t cnt)
201 {
202 const char *b = buf;
203
204 while (cnt) {
205 ssize_t r;
206 #ifdef GIT_WIN32
207 GIT_ASSERT((size_t)((unsigned int)cnt) == cnt);
208 r = write(fd, b, (unsigned int)cnt);
209 #else
210 r = write(fd, b, cnt);
211 #endif
212 if (r < 0) {
213 if (errno == EINTR || GIT_ISBLOCKED(errno))
214 continue;
215 return -1;
216 }
217 if (!r) {
218 errno = EPIPE;
219 return -1;
220 }
221 cnt -= r;
222 b += r;
223 }
224 return 0;
225 }
226
227 #ifdef NO_MMAP
228
229 #include "map.h"
230
231 int git__page_size(size_t *page_size)
232 {
233 /* dummy; here we don't need any alignment anyway */
234 *page_size = 4096;
235 return 0;
236 }
237
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
245
246 int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset)
247 {
248 const char *ptr;
249 size_t remaining_len;
250
251 GIT_MMAP_VALIDATE(out, len, prot, flags);
252
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 }
260
261 if (!git__is_ssizet(len)) {
262 errno = EINVAL;
263 return -1;
264 }
265
266 out->len = 0;
267 out->data = git__malloc(len);
268 GIT_ERROR_CHECK_ALLOC(out->data);
269
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;
285 }
286
287 out->len = len;
288 return 0;
289 }
290
291 int p_munmap(git_map *map)
292 {
293 GIT_ASSERT_ARG(map);
294 git__free(map->data);
295
296 /* Initializing will help debug use-after-free */
297 map->len = 0;
298 map->data = NULL;
299
300 return 0;
301 }
302
303 #endif