]> git.proxmox.com Git - libgit2.git/blob - src/posix.c
New upstream version 1.1.0+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 "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 if (flags & O_CREAT) {
113 va_list arg_list;
114
115 va_start(arg_list, flags);
116 mode = (mode_t)va_arg(arg_list, int);
117 va_end(arg_list);
118 }
119
120 return open(path, flags | O_BINARY | O_CLOEXEC, mode);
121 }
122
123 int p_creat(const char *path, mode_t mode)
124 {
125 return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC, mode);
126 }
127
128 int p_getcwd(char *buffer_out, size_t size)
129 {
130 char *cwd_buffer;
131
132 assert(buffer_out && size > 0);
133
134 cwd_buffer = getcwd(buffer_out, size);
135
136 if (cwd_buffer == NULL)
137 return -1;
138
139 git_path_mkposix(buffer_out);
140 git_path_string_to_dir(buffer_out, size); /* append trailing slash */
141
142 return 0;
143 }
144
145 int p_rename(const char *from, const char *to)
146 {
147 if (!link(from, to)) {
148 p_unlink(from);
149 return 0;
150 }
151
152 if (!rename(from, to))
153 return 0;
154
155 return -1;
156 }
157
158 #endif /* GIT_WIN32 */
159
160 ssize_t p_read(git_file fd, void *buf, size_t cnt)
161 {
162 char *b = buf;
163
164 if (!git__is_ssizet(cnt)) {
165 #ifdef GIT_WIN32
166 SetLastError(ERROR_INVALID_PARAMETER);
167 #endif
168 errno = EINVAL;
169 return -1;
170 }
171
172 while (cnt) {
173 ssize_t r;
174 #ifdef GIT_WIN32
175 r = read(fd, b, cnt > INT_MAX ? INT_MAX : (unsigned int)cnt);
176 #else
177 r = read(fd, b, cnt);
178 #endif
179 if (r < 0) {
180 if (errno == EINTR || errno == EAGAIN)
181 continue;
182 return -1;
183 }
184 if (!r)
185 break;
186 cnt -= r;
187 b += r;
188 }
189 return (b - (char *)buf);
190 }
191
192 int p_write(git_file fd, const void *buf, size_t cnt)
193 {
194 const char *b = buf;
195
196 while (cnt) {
197 ssize_t r;
198 #ifdef GIT_WIN32
199 assert((size_t)((unsigned int)cnt) == cnt);
200 r = write(fd, b, (unsigned int)cnt);
201 #else
202 r = write(fd, b, cnt);
203 #endif
204 if (r < 0) {
205 if (errno == EINTR || GIT_ISBLOCKED(errno))
206 continue;
207 return -1;
208 }
209 if (!r) {
210 errno = EPIPE;
211 return -1;
212 }
213 cnt -= r;
214 b += r;
215 }
216 return 0;
217 }
218
219 #ifdef NO_MMAP
220
221 #include "map.h"
222
223 int git__page_size(size_t *page_size)
224 {
225 /* dummy; here we don't need any alignment anyway */
226 *page_size = 4096;
227 return 0;
228 }
229
230 int git__mmap_alignment(size_t *alignment)
231 {
232 /* dummy; here we don't need any alignment anyway */
233 *alignment = 4096;
234 return 0;
235 }
236
237
238 int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, off64_t offset)
239 {
240 GIT_MMAP_VALIDATE(out, len, prot, flags);
241
242 out->data = NULL;
243 out->len = 0;
244
245 if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) {
246 git_error_set(GIT_ERROR_OS, "trying to map shared-writeable");
247 return -1;
248 }
249
250 out->data = git__malloc(len);
251 GIT_ERROR_CHECK_ALLOC(out->data);
252
253 if (!git__is_ssizet(len) ||
254 (p_lseek(fd, offset, SEEK_SET) < 0) ||
255 (p_read(fd, out->data, len) != (ssize_t)len)) {
256 git_error_set(GIT_ERROR_OS, "mmap emulation failed");
257 return -1;
258 }
259
260 out->len = len;
261 return 0;
262 }
263
264 int p_munmap(git_map *map)
265 {
266 assert(map != NULL);
267 git__free(map->data);
268
269 return 0;
270 }
271
272 #endif