File Coverage

deps/libgit2/src/util/posix.c
Criterion Covered Total %
statement 35 54 64.8
branch 16 38 42.1
condition n/a
subroutine n/a
pod n/a
total 51 92 55.4


line stmt bran cond sub pod time code
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
12             #include
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 4170           int p_open(const char *path, volatile int flags, ...)
109             {
110 4170           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 4170 100         if (flags & O_CREAT) {
120             va_list arg_list;
121              
122 700           va_start(arg_list, flags);
123 700 50         mode = (mode_t)va_arg(arg_list, int);
124 700           va_end(arg_list);
125             }
126              
127 4170           return open(path, flags | O_BINARY | O_CLOEXEC, mode);
128             }
129              
130 5           int p_creat(const char *path, mode_t mode)
131             {
132 5           return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC, mode);
133             }
134              
135 0           int p_getcwd(char *buffer_out, size_t size)
136             {
137             char *cwd_buffer;
138              
139 0 0         GIT_ASSERT_ARG(buffer_out);
140 0 0         GIT_ASSERT_ARG(size > 0);
141              
142 0           cwd_buffer = getcwd(buffer_out, size);
143              
144 0 0         if (cwd_buffer == NULL)
145 0           return -1;
146              
147             git_fs_path_mkposix(buffer_out);
148 0           git_fs_path_string_to_dir(buffer_out, size); /* append trailing slash */
149              
150 0           return 0;
151             }
152              
153 463           int p_rename(const char *from, const char *to)
154             {
155 463 100         if (!link(from, to)) {
156 236           p_unlink(from);
157 236           return 0;
158             }
159              
160 227 50         if (!rename(from, to))
161 227           return 0;
162              
163 0           return -1;
164             }
165              
166             #endif /* GIT_WIN32 */
167              
168 3127           ssize_t p_read(git_file fd, void *buf, size_t cnt)
169             {
170 3127           char *b = buf;
171              
172 3127 50         if (!git__is_ssizet(cnt)) {
173             #ifdef GIT_WIN32
174             SetLastError(ERROR_INVALID_PARAMETER);
175             #endif
176 0           errno = EINVAL;
177 0           return -1;
178             }
179              
180 6168 100         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 3659           r = read(fd, b, cnt);
186             #endif
187 3659 50         if (r < 0) {
188 0 0         if (errno == EINTR || errno == EAGAIN)
    0          
189 0           continue;
190 0           return -1;
191             }
192 3659 100         if (!r)
193 618           break;
194 3041           cnt -= r;
195 3041           b += r;
196             }
197 3127           return (b - (char *)buf);
198             }
199              
200 751           int p_write(git_file fd, const void *buf, size_t cnt)
201             {
202 751           const char *b = buf;
203              
204 1502 100         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 751           r = write(fd, b, cnt);
211             #endif
212 751 50         if (r < 0) {
213 0 0         if (errno == EINTR || GIT_ISBLOCKED(errno))
    0          
    0          
214 0           continue;
215 0           return -1;
216             }
217 751 50         if (!r) {
218 0           errno = EPIPE;
219 0           return -1;
220             }
221 751           cnt -= r;
222 751           b += r;
223             }
224 751           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