wrapper.c 12.9 KB
Newer Older
1 2 3 4 5
/*
 * Various trivial helper wrappers around standard functions
 */
#include "cache.h"

6
static void do_nothing(size_t size)
7 8 9
{
}

10
static void (*try_to_free_routine)(size_t size) = do_nothing;
11

12
static int memory_limit_check(size_t size, int gentle)
13
{
14 15 16 17 18
	static size_t limit = 0;
	if (!limit) {
		limit = git_env_ulong("GIT_ALLOC_LIMIT", 0);
		if (!limit)
			limit = SIZE_MAX;
19
	}
20
	if (size > limit) {
21
		if (gentle) {
22 23
			error("attempting to allocate %"PRIuMAX" over limit %"PRIuMAX,
			      (uintmax_t)size, (uintmax_t)limit);
24 25
			return -1;
		} else
26 27
			die("attempting to allocate %"PRIuMAX" over limit %"PRIuMAX,
			    (uintmax_t)size, (uintmax_t)limit);
28 29
	}
	return 0;
30 31
}

32
try_to_free_t set_try_to_free_routine(try_to_free_t routine)
33
{
34
	try_to_free_t old = try_to_free_routine;
35 36
	if (!routine)
		routine = do_nothing;
37 38
	try_to_free_routine = routine;
	return old;
39 40
}

41 42 43 44
char *xstrdup(const char *str)
{
	char *ret = strdup(str);
	if (!ret) {
45
		try_to_free_routine(strlen(str) + 1);
46 47 48 49 50 51 52
		ret = strdup(str);
		if (!ret)
			die("Out of memory, strdup failed");
	}
	return ret;
}

53
static void *do_xmalloc(size_t size, int gentle)
54
{
55 56
	void *ret;

57 58
	if (memory_limit_check(size, gentle))
		return NULL;
59
	ret = malloc(size);
60 61 62
	if (!ret && !size)
		ret = malloc(1);
	if (!ret) {
63
		try_to_free_routine(size);
64 65 66
		ret = malloc(size);
		if (!ret && !size)
			ret = malloc(1);
67 68 69 70 71 72 73 74 75 76
		if (!ret) {
			if (!gentle)
				die("Out of memory, malloc failed (tried to allocate %lu bytes)",
				    (unsigned long)size);
			else {
				error("Out of memory, malloc failed (tried to allocate %lu bytes)",
				      (unsigned long)size);
				return NULL;
			}
		}
77 78 79 80 81 82 83
	}
#ifdef XMALLOC_POISON
	memset(ret, 0xA5, size);
#endif
	return ret;
}

84 85 86 87 88 89
void *xmalloc(size_t size)
{
	return do_xmalloc(size, 0);
}

static void *do_xmallocz(size_t size, int gentle)
I
Ilari Liusvaara 已提交
90 91
{
	void *ret;
92 93 94 95 96 97 98 99 100 101
	if (unsigned_add_overflows(size, 1)) {
		if (gentle) {
			error("Data too large to fit into virtual memory space.");
			return NULL;
		} else
			die("Data too large to fit into virtual memory space.");
	}
	ret = do_xmalloc(size + 1, gentle);
	if (ret)
		((char*)ret)[size] = 0;
I
Ilari Liusvaara 已提交
102 103 104
	return ret;
}

105 106 107 108 109 110 111 112 113 114
void *xmallocz(size_t size)
{
	return do_xmallocz(size, 0);
}

void *xmallocz_gently(size_t size)
{
	return do_xmallocz(size, 1);
}

115 116 117 118 119 120 121 122
/*
 * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
 * "data" to the allocated memory, zero terminates the allocated memory,
 * and returns a pointer to the allocated memory. If the allocation fails,
 * the program dies.
 */
void *xmemdupz(const void *data, size_t len)
{
I
Ilari Liusvaara 已提交
123
	return memcpy(xmallocz(len), data, len);
124 125 126 127 128 129 130 131 132 133
}

char *xstrndup(const char *str, size_t len)
{
	char *p = memchr(str, '\0', len);
	return xmemdupz(str, p ? p - str : len);
}

void *xrealloc(void *ptr, size_t size)
{
134 135
	void *ret;

136
	memory_limit_check(size, 0);
137
	ret = realloc(ptr, size);
138 139 140
	if (!ret && !size)
		ret = realloc(ptr, 1);
	if (!ret) {
141
		try_to_free_routine(size);
142 143 144 145 146 147 148 149 150 151 152
		ret = realloc(ptr, size);
		if (!ret && !size)
			ret = realloc(ptr, 1);
		if (!ret)
			die("Out of memory, realloc failed");
	}
	return ret;
}

void *xcalloc(size_t nmemb, size_t size)
{
153 154
	void *ret;

155
	memory_limit_check(size * nmemb, 0);
156
	ret = calloc(nmemb, size);
157 158 159
	if (!ret && (!nmemb || !size))
		ret = calloc(1, 1);
	if (!ret) {
160
		try_to_free_routine(nmemb * size);
161 162 163 164 165 166 167 168 169
		ret = calloc(nmemb, size);
		if (!ret && (!nmemb || !size))
			ret = calloc(1, 1);
		if (!ret)
			die("Out of memory, calloc failed");
	}
	return ret;
}

170 171 172
/*
 * Limit size of IO chunks, because huge chunks only cause pain.  OS X
 * 64-bit is buggy, returning EINVAL if len >= INT_MAX; and even in
M
Masanari Iida 已提交
173
 * the absence of bugs, large chunks can result in bad latencies when
174
 * you decide to kill the process.
175 176 177 178 179 180 181
 *
 * We pick 8 MiB as our default, but if the platform defines SSIZE_MAX
 * that is smaller than that, clip it to SSIZE_MAX, as a call to
 * read(2) or write(2) larger than that is allowed to fail.  As the last
 * resort, we allow a port to pass via CFLAGS e.g. "-DMAX_IO_SIZE=value"
 * to override this, if the definition of SSIZE_MAX given by the platform
 * is broken.
182
 */
183 184 185 186 187 188 189 190
#ifndef MAX_IO_SIZE
# define MAX_IO_SIZE_DEFAULT (8*1024*1024)
# if defined(SSIZE_MAX) && (SSIZE_MAX < MAX_IO_SIZE_DEFAULT)
#  define MAX_IO_SIZE SSIZE_MAX
# else
#  define MAX_IO_SIZE MAX_IO_SIZE_DEFAULT
# endif
#endif
191

192 193 194 195 196 197 198 199
/*
 * xread() is the same a read(), but it automatically restarts read()
 * operations with a recoverable error (EAGAIN and EINTR). xread()
 * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
 */
ssize_t xread(int fd, void *buf, size_t len)
{
	ssize_t nr;
200 201
	if (len > MAX_IO_SIZE)
	    len = MAX_IO_SIZE;
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
	while (1) {
		nr = read(fd, buf, len);
		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
			continue;
		return nr;
	}
}

/*
 * xwrite() is the same a write(), but it automatically restarts write()
 * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
 * GUARANTEE that "len" bytes is written even if the operation is successful.
 */
ssize_t xwrite(int fd, const void *buf, size_t len)
{
	ssize_t nr;
218 219
	if (len > MAX_IO_SIZE)
	    len = MAX_IO_SIZE;
220 221 222
	while (1) {
		nr = write(fd, buf, len);
		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
			continue;
		return nr;
	}
}

/*
 * xpread() is the same as pread(), but it automatically restarts pread()
 * operations with a recoverable error (EAGAIN and EINTR). xpread() DOES
 * NOT GUARANTEE that "len" bytes is read even if the data is available.
 */
ssize_t xpread(int fd, void *buf, size_t len, off_t offset)
{
	ssize_t nr;
	if (len > MAX_IO_SIZE)
		len = MAX_IO_SIZE;
	while (1) {
		nr = pread(fd, buf, len, offset);
		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
241 242 243 244 245
			continue;
		return nr;
	}
}

246 247 248 249 250 251 252
ssize_t read_in_full(int fd, void *buf, size_t count)
{
	char *p = buf;
	ssize_t total = 0;

	while (count > 0) {
		ssize_t loaded = xread(fd, p, count);
J
Jeff King 已提交
253 254 255 256
		if (loaded < 0)
			return -1;
		if (loaded == 0)
			return total;
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285
		count -= loaded;
		p += loaded;
		total += loaded;
	}

	return total;
}

ssize_t write_in_full(int fd, const void *buf, size_t count)
{
	const char *p = buf;
	ssize_t total = 0;

	while (count > 0) {
		ssize_t written = xwrite(fd, p, count);
		if (written < 0)
			return -1;
		if (!written) {
			errno = ENOSPC;
			return -1;
		}
		count -= written;
		p += written;
		total += written;
	}

	return total;
}

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
{
	char *p = buf;
	ssize_t total = 0;

	while (count > 0) {
		ssize_t loaded = xpread(fd, p, count, offset);
		if (loaded < 0)
			return -1;
		if (loaded == 0)
			return total;
		count -= loaded;
		p += loaded;
		total += loaded;
		offset += loaded;
	}

	return total;
}

306 307 308 309
int xdup(int fd)
{
	int ret = dup(fd);
	if (ret < 0)
310
		die_errno("dup failed");
311 312 313 314 315 316 317
	return ret;
}

FILE *xfdopen(int fd, const char *mode)
{
	FILE *stream = fdopen(fd, mode);
	if (stream == NULL)
318
		die_errno("Out of memory? fdopen failed");
319 320 321 322 323 324
	return stream;
}

int xmkstemp(char *template)
{
	int fd;
325 326
	char origtemplate[PATH_MAX];
	strlcpy(origtemplate, template, sizeof(origtemplate));
327 328

	fd = mkstemp(template);
329 330 331 332
	if (fd < 0) {
		int saved_errno = errno;
		const char *nonrelative_template;

333
		if (strlen(template) != strlen(origtemplate))
334 335
			template = origtemplate;

336
		nonrelative_template = absolute_path(template);
337 338 339 340
		errno = saved_errno;
		die_errno("Unable to create temporary file '%s'",
			nonrelative_template);
	}
341 342
	return fd;
}
343

344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
/* git_mkstemp() - create tmp file honoring TMPDIR variable */
int git_mkstemp(char *path, size_t len, const char *template)
{
	const char *tmp;
	size_t n;

	tmp = getenv("TMPDIR");
	if (!tmp)
		tmp = "/tmp";
	n = snprintf(path, len, "%s/%s", tmp, template);
	if (len <= n) {
		errno = ENAMETOOLONG;
		return -1;
	}
	return mkstemp(path);
}

/* git_mkstemps() - create tmp file with suffix honoring TMPDIR variable. */
int git_mkstemps(char *path, size_t len, const char *template, int suffix_len)
{
	const char *tmp;
	size_t n;

	tmp = getenv("TMPDIR");
	if (!tmp)
		tmp = "/tmp";
	n = snprintf(path, len, "%s/%s", tmp, template);
	if (len <= n) {
		errno = ENAMETOOLONG;
		return -1;
	}
	return mkstemps(path, suffix_len);
}

/* Adapted from libiberty's mkstemp.c. */

#undef TMP_MAX
#define TMP_MAX 16384

int git_mkstemps_mode(char *pattern, int suffix_len, int mode)
{
	static const char letters[] =
		"abcdefghijklmnopqrstuvwxyz"
		"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		"0123456789";
	static const int num_letters = 62;
	uint64_t value;
	struct timeval tv;
	char *template;
	size_t len;
	int fd, count;

	len = strlen(pattern);

	if (len < 6 + suffix_len) {
		errno = EINVAL;
		return -1;
	}

	if (strncmp(&pattern[len - 6 - suffix_len], "XXXXXX", 6)) {
		errno = EINVAL;
		return -1;
	}

	/*
	 * Replace pattern's XXXXXX characters with randomness.
	 * Try TMP_MAX different filenames.
	 */
	gettimeofday(&tv, NULL);
	value = ((size_t)(tv.tv_usec << 16)) ^ tv.tv_sec ^ getpid();
	template = &pattern[len - 6 - suffix_len];
	for (count = 0; count < TMP_MAX; ++count) {
		uint64_t v = value;
		/* Fill in the random bits. */
		template[0] = letters[v % num_letters]; v /= num_letters;
		template[1] = letters[v % num_letters]; v /= num_letters;
		template[2] = letters[v % num_letters]; v /= num_letters;
		template[3] = letters[v % num_letters]; v /= num_letters;
		template[4] = letters[v % num_letters]; v /= num_letters;
		template[5] = letters[v % num_letters]; v /= num_letters;

		fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);
426
		if (fd >= 0)
427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451
			return fd;
		/*
		 * Fatal error (EPERM, ENOSPC etc).
		 * It doesn't make sense to loop.
		 */
		if (errno != EEXIST)
			break;
		/*
		 * This is a random value.  It is only necessary that
		 * the next TMP_MAX values generated by adding 7777 to
		 * VALUE are different with (module 2^32).
		 */
		value += 7777;
	}
	/* We return the null string if we can't find a unique file name.  */
	pattern[0] = '\0';
	return -1;
}

int git_mkstemp_mode(char *pattern, int mode)
{
	/* mkstemp is just mkstemps with no suffix */
	return git_mkstemps_mode(pattern, 0, mode);
}

452
#ifdef NO_MKSTEMPS
453 454 455 456
int gitmkstemps(char *pattern, int suffix_len)
{
	return git_mkstemps_mode(pattern, suffix_len, 0600);
}
457
#endif
458

459 460 461
int xmkstemp_mode(char *template, int mode)
{
	int fd;
462 463
	char origtemplate[PATH_MAX];
	strlcpy(origtemplate, template, sizeof(origtemplate));
464 465

	fd = git_mkstemp_mode(template, mode);
466 467 468 469 470 471 472
	if (fd < 0) {
		int saved_errno = errno;
		const char *nonrelative_template;

		if (!template[0])
			template = origtemplate;

473
		nonrelative_template = absolute_path(template);
474 475 476 477
		errno = saved_errno;
		die_errno("Unable to create temporary file '%s'",
			nonrelative_template);
	}
478 479 480
	return fd;
}

481
static int warn_if_unremovable(const char *op, const char *file, int rc)
482
{
483 484 485 486 487 488
	int err;
	if (!rc || errno == ENOENT)
		return 0;
	err = errno;
	warning("unable to %s %s: %s", op, file, strerror(errno));
	errno = err;
489 490 491
	return rc;
}

492 493 494 495 496 497 498 499 500 501 502 503 504 505
int unlink_or_msg(const char *file, struct strbuf *err)
{
	int rc = unlink(file);

	assert(err);

	if (!rc || errno == ENOENT)
		return 0;

	strbuf_addf(err, "unable to unlink %s: %s",
		    file, strerror(errno));
	return -1;
}

506 507 508 509
int unlink_or_warn(const char *file)
{
	return warn_if_unremovable("unlink", file, unlink(file));
}
510 511 512 513 514

int rmdir_or_warn(const char *file)
{
	return warn_if_unremovable("rmdir", file, rmdir(file));
}
515 516 517 518 519

int remove_or_warn(unsigned int mode, const char *file)
{
	return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
}
520

521 522 523 524 525
void warn_on_inaccessible(const char *path)
{
	warning(_("unable to access '%s': %s"), path, strerror(errno));
}

526 527 528 529 530 531 532
static int access_error_is_ok(int err, unsigned flag)
{
	return err == ENOENT || err == ENOTDIR ||
		((flag & ACCESS_EACCES_OK) && err == EACCES);
}

int access_or_warn(const char *path, int mode, unsigned flag)
J
Jeff King 已提交
533 534
{
	int ret = access(path, mode);
535
	if (ret && !access_error_is_ok(errno, flag))
536
		warn_on_inaccessible(path);
J
Jeff King 已提交
537 538 539
	return ret;
}

540
int access_or_die(const char *path, int mode, unsigned flag)
541 542
{
	int ret = access(path, mode);
543
	if (ret && !access_error_is_ok(errno, flag))
544 545 546 547
		die_errno(_("unable to access '%s'"), path);
	return ret;
}

548 549 550 551 552 553 554 555 556 557 558
struct passwd *xgetpwuid_self(void)
{
	struct passwd *pw;

	errno = 0;
	pw = getpwuid(getuid());
	if (!pw)
		die(_("unable to look up current user in the passwd file: %s"),
		    errno ? strerror(errno) : _("no such user"));
	return pw;
}
R
René Scharfe 已提交
559 560 561 562 563 564 565 566

char *xgetcwd(void)
{
	struct strbuf sb = STRBUF_INIT;
	if (strbuf_getcwd(&sb))
		die_errno(_("unable to get current working directory"));
	return strbuf_detach(&sb, NULL);
}
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597

int write_file(const char *path, int fatal, const char *fmt, ...)
{
	struct strbuf sb = STRBUF_INIT;
	va_list params;
	int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0666);
	if (fd < 0) {
		if (fatal)
			die_errno(_("could not open %s for writing"), path);
		return -1;
	}
	va_start(params, fmt);
	strbuf_vaddf(&sb, fmt, params);
	va_end(params);
	if (write_in_full(fd, sb.buf, sb.len) != sb.len) {
		int err = errno;
		close(fd);
		strbuf_release(&sb);
		errno = err;
		if (fatal)
			die_errno(_("could not write to %s"), path);
		return -1;
	}
	strbuf_release(&sb);
	if (close(fd)) {
		if (fatal)
			die_errno(_("could not close %s"), path);
		return -1;
	}
	return 0;
}
598 599 600 601 602

void sleep_millisec(int millisec)
{
	poll(NULL, 0, millisec);
}