posix.c 4.73 KB
Newer Older
Vicent Marti committed
1
/*
Edward Thomson committed
2
 * Copyright (C) the libgit2 contributors. All rights reserved.
Vicent Marti committed
3 4 5 6
 *
 * This file is part of libgit2, distributed under the GNU GPL v2 with
 * a Linking Exception. For full terms see the included COPYING file.
 */
Vicent Marti committed
7 8 9 10 11 12
#include "common.h"
#include "posix.h"
#include "path.h"
#include <stdio.h>
#include <ctype.h>

13 14
#ifndef GIT_WIN32

Vicent Marti committed
15
#ifdef NO_ADDRINFO
16

Vicent Marti committed
17 18 19 20 21 22 23 24
int p_getaddrinfo(
	const char *host,
	const char *port,
	struct addrinfo *hints,
	struct addrinfo **info)
{
	struct addrinfo *ainfo, *ai;
	int p = 0;
25 26 27

	GIT_UNUSED(hints);

Vicent Marti committed
28 29
	if ((ainfo = malloc(sizeof(struct addrinfo))) == NULL)
		return -1;
30 31 32

	if ((ainfo->ai_hostent = gethostbyname(host)) == NULL) {
		free(ainfo);
Vicent Marti committed
33
		return -2;
34 35
	}

Vicent Marti committed
36
	ainfo->ai_servent = getservbyname(port, 0);
37

Vicent Marti committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
	if (ainfo->ai_servent)
		ainfo->ai_port = ainfo->ai_servent->s_port;
	else
		ainfo->ai_port = atol(port);

	memcpy(&ainfo->ai_addr_in.sin_addr,
			ainfo->ai_hostent->h_addr_list[0],
			ainfo->ai_hostent->h_length);

	ainfo->ai_protocol = 0;
	ainfo->ai_socktype = hints->ai_socktype;
	ainfo->ai_family = ainfo->ai_hostent->h_addrtype;
	ainfo->ai_addr_in.sin_family = ainfo->ai_family;
	ainfo->ai_addr_in.sin_port = ainfo->ai_port;
	ainfo->ai_addr = (struct addrinfo *)&ainfo->ai_addr_in;
	ainfo->ai_addrlen = sizeof(struct sockaddr_in);

	*info = ainfo;
56

Vicent Marti committed
57 58 59 60
	if (ainfo->ai_hostent->h_addr_list[1] == NULL) {
		ainfo->ai_next = NULL;
		return 0;
	}
61

Vicent Marti committed
62
	ai = ainfo;
63

Vicent Marti committed
64 65 66 67 68 69 70 71 72
	for (p = 1; ainfo->ai_hostent->h_addr_list[p] != NULL; p++) {
		ai->ai_next = malloc(sizeof(struct addrinfo));
		memcpy(&ai->ai_next, ainfo, sizeof(struct addrinfo));
		memcpy(&ai->ai_next->ai_addr_in.sin_addr,
			ainfo->ai_hostent->h_addr_list[p],
			ainfo->ai_hostent->h_length);
		ai->ai_next->ai_addr = (struct addrinfo *)&ai->ai_next->ai_addr_in;
		ai = ai->ai_next;
	}
73

Vicent Marti committed
74 75 76 77 78 79 80
	ai->ai_next = NULL;
	return 0;
}

void p_freeaddrinfo(struct addrinfo *info)
{
	struct addrinfo *p, *next;
81

Vicent Marti committed
82
	p = info;
83

Vicent Marti committed
84 85 86 87 88 89 90 91 92 93
	while(p != NULL) {
		next = p->ai_next;
		free(p);
		p = next;
	}
}

const char *p_gai_strerror(int ret)
{
	switch(ret) {
94 95 96
	case -1: return "Out of memory"; break;
	case -2: return "Address lookup failed"; break;
	default: return "Unknown error"; break;
Vicent Marti committed
97 98
	}
}
99

Vicent Marti committed
100 101
#endif /* NO_ADDRINFO */

102
int p_open(const char *path, volatile int flags, ...)
Vicent Marti committed
103
{
104 105
	mode_t mode = 0;

106
	if (flags & O_CREAT) {
107 108 109
		va_list arg_list;

		va_start(arg_list, flags);
110
		mode = (mode_t)va_arg(arg_list, int);
111 112 113
		va_end(arg_list);
	}

114
	return open(path, flags | O_BINARY | O_CLOEXEC, mode);
Vicent Marti committed
115 116
}

117
int p_creat(const char *path, mode_t mode)
Vicent Marti committed
118
{
119
	return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC, mode);
Vicent Marti committed
120 121
}

122 123 124 125 126 127 128 129 130
int p_getcwd(char *buffer_out, size_t size)
{
	char *cwd_buffer;

	assert(buffer_out && size > 0);

	cwd_buffer = getcwd(buffer_out, size);

	if (cwd_buffer == NULL)
131
		return -1;
132 133

	git_path_mkposix(buffer_out);
134
	git_path_string_to_dir(buffer_out, size); /* append trailing slash */
135

136
	return 0;
137 138
}

139 140 141 142
int p_rename(const char *from, const char *to)
{
	if (!link(from, to)) {
		p_unlink(from);
143
		return 0;
144 145 146
	}

	if (!rename(from, to))
147
		return 0;
148

149
	return -1;
150 151
}

Vicent Marti committed
152
#endif /* GIT_WIN32 */
153

154
ssize_t p_read(git_file fd, void *buf, size_t cnt)
Vicent Marti committed
155 156
{
	char *b = buf;
157

158 159 160 161 162 163 164 165
	if (!git__is_ssizet(cnt)) {
#ifdef GIT_WIN32
		SetLastError(ERROR_INVALID_PARAMETER);
#endif
		errno = EINVAL;
		return -1;
	}

Vicent Marti committed
166
	while (cnt) {
167 168
		ssize_t r;
#ifdef GIT_WIN32
169
		r = read(fd, b, cnt > INT_MAX ? INT_MAX : (unsigned int)cnt);
170 171 172
#else
		r = read(fd, b, cnt);
#endif
Vicent Marti committed
173 174 175
		if (r < 0) {
			if (errno == EINTR || errno == EAGAIN)
				continue;
176
			return -1;
Vicent Marti committed
177 178 179 180 181 182
		}
		if (!r)
			break;
		cnt -= r;
		b += r;
	}
183
	return (b - (char *)buf);
Vicent Marti committed
184 185
}

186
int p_write(git_file fd, const void *buf, size_t cnt)
Vicent Marti committed
187
{
188
	const char *b = buf;
189

Vicent Marti committed
190
	while (cnt) {
191 192 193 194 195 196 197
		ssize_t r;
#ifdef GIT_WIN32
		assert((size_t)((unsigned int)cnt) == cnt);
		r = write(fd, b, (unsigned int)cnt);
#else
		r = write(fd, b, cnt);
#endif
Vicent Marti committed
198
		if (r < 0) {
199
			if (errno == EINTR || GIT_ISBLOCKED(errno))
Vicent Marti committed
200
				continue;
201
			return -1;
Vicent Marti committed
202 203 204
		}
		if (!r) {
			errno = EPIPE;
205
			return -1;
Vicent Marti committed
206 207 208 209
		}
		cnt -= r;
		b += r;
	}
210
	return 0;
Vicent Marti committed
211
}
212

213
#ifdef NO_MMAP
214

215 216
#include "map.h"

217
int git__page_size(size_t *page_size)
218 219
{
	/* dummy; here we don't need any alignment anyway */
220 221
	*page_size = 4096;
	return 0;
222 223 224
}


225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
int p_mmap(git_map *out, size_t len, int prot, int flags, int fd, git_off_t offset)
{
	GIT_MMAP_VALIDATE(out, len, prot, flags);

	out->data = NULL;
	out->len = 0;

	if ((prot & GIT_PROT_WRITE) && ((flags & GIT_MAP_TYPE) == GIT_MAP_SHARED)) {
		giterr_set(GITERR_OS, "Trying to map shared-writeable");
		return -1;
	}

	out->data = malloc(len);
	GITERR_CHECK_ALLOC(out->data);

240 241 242
	if (!git__is_ssizet(len) ||
		(p_lseek(fd, offset, SEEK_SET) < 0) ||
		(p_read(fd, out->data, len) != (ssize_t)len)) {
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
		giterr_set(GITERR_OS, "mmap emulation failed");
		return -1;
	}

	out->len = len;
	return 0;
}

int p_munmap(git_map *map)
{
	assert(map != NULL);
	free(map->data);

	return 0;
}

#endif