diff lib/swig/swigwin-2.0.11/CCache/util.c @ 1899:b3009adc0e2f

Adding swig, gitignore, hgignore
author Nomad
date Mon, 21 Oct 2013 10:42:27 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/swig/swigwin-2.0.11/CCache/util.c	Mon Oct 21 10:42:27 2013 +0200
@@ -0,0 +1,884 @@
+/*
+   Copyright (C) Andrew Tridgell 2002
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "ccache.h"
+
+static FILE *logfile;
+
+/* log a message to the CCACHE_LOGFILE location */
+void cc_log(const char *format, ...)
+{
+	va_list ap;
+	extern char *cache_logfile;
+
+	if (!cache_logfile) return;
+
+	if (!logfile) logfile = fopen(cache_logfile, "a");
+	if (!logfile) return;
+	
+	va_start(ap, format);
+	vfprintf(logfile, format, ap);
+	va_end(ap);
+	fflush(logfile);
+}
+
+/* something went badly wrong! */
+void fatal(const char *msg)
+{
+	cc_log("FATAL: %s\n", msg);
+	exit(1);
+}
+
+int safe_rename(const char* oldpath, const char* newpath)
+{
+	/* safe_rename is for creating entries in the cache.
+
+	   Works like rename(), but it never overwrites an existing
+	   cache entry. This avoids corruption on NFS. */
+#ifndef _WIN32
+	int status = link(oldpath, newpath);
+	if( status == 0 || errno == EEXIST )
+#else
+	int status = CreateHardLinkA(newpath, oldpath, NULL) ? 0 : -1;
+	if( status == 0 || GetLastError() == ERROR_ALREADY_EXISTS )
+#endif
+	{
+		return unlink( oldpath );
+	}
+	else
+	{
+		return -1;
+	}
+}
+ 
+#ifndef ENABLE_ZLIB
+/* copy all data from one file descriptor to another */
+void copy_fd(int fd_in, int fd_out)
+{
+	char buf[10240];
+	int n;
+
+	while ((n = read(fd_in, buf, sizeof(buf))) > 0) {
+		if (write(fd_out, buf, n) != n) {
+			fatal("Failed to copy fd");
+		}
+	}
+}
+
+#ifndef HAVE_MKSTEMP
+/* cheap and nasty mkstemp replacement */
+int mkstemp(char *template)
+{
+	mktemp(template);
+	return open(template, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
+}
+#endif
+
+/* move a file using rename */
+int move_file(const char *src, const char *dest) {
+	return safe_rename(src, dest);
+}
+
+/* copy a file - used when hard links don't work 
+   the copy is done via a temporary file and atomic rename
+*/
+static int copy_file(const char *src, const char *dest)
+{
+	int fd1, fd2;
+	char buf[10240];
+	int n;
+	char *tmp_name;
+	mode_t mask;
+
+	x_asprintf(&tmp_name, "%s.XXXXXX", dest);
+
+	fd1 = open(src, O_RDONLY|O_BINARY);
+	if (fd1 == -1) {
+		free(tmp_name);
+		return -1;
+	}
+
+	fd2 = mkstemp(tmp_name);
+	if (fd2 == -1) {
+		close(fd1);
+		free(tmp_name);
+		return -1;
+	}
+
+	while ((n = read(fd1, buf, sizeof(buf))) > 0) {
+		if (write(fd2, buf, n) != n) {
+			close(fd2);
+			close(fd1);
+			unlink(tmp_name);
+			free(tmp_name);
+			return -1;
+		}
+	}
+
+	close(fd1);
+
+	/* get perms right on the tmp file */
+#ifndef _WIN32
+	mask = umask(0);
+	fchmod(fd2, 0666 & ~mask);
+	umask(mask);
+#else
+	(void)mask;
+#endif
+
+	/* the close can fail on NFS if out of space */
+	if (close(fd2) == -1) {
+		unlink(tmp_name);
+		free(tmp_name);
+		return -1;
+	}
+
+	unlink(dest);
+
+	if (rename(tmp_name, dest) == -1) {
+		unlink(tmp_name);
+		free(tmp_name);
+		return -1;
+	}
+
+	free(tmp_name);
+
+	return 0;
+}
+
+/* copy a file to the cache */
+static int copy_file_to_cache(const char *src, const char *dest) {
+	return copy_file(src, dest);
+}
+
+/* copy a file from the cache */
+static int copy_file_from_cache(const char *src, const char *dest) {
+	return copy_file(src, dest);
+}
+
+#else /* ENABLE_ZLIB */
+
+/* copy all data from one file descriptor to another
+   possibly decompressing it
+*/
+void copy_fd(int fd_in, int fd_out) {
+	char buf[10240];
+	int n;
+	gzFile gz_in;
+
+	gz_in = gzdopen(dup(fd_in), "rb");
+
+	if (!gz_in) {
+		fatal("Failed to copy fd");
+	}
+
+	while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
+		if (write(fd_out, buf, n) != n) {
+			fatal("Failed to copy fd");
+		}
+	}
+}
+
+static int _copy_file(const char *src, const char *dest, int mode) {
+	int fd_in, fd_out;
+	gzFile gz_in, gz_out = NULL;
+	char buf[10240];
+	int n, ret;
+	char *tmp_name;
+	mode_t mask;
+	struct stat st;
+
+	x_asprintf(&tmp_name, "%s.XXXXXX", dest);
+
+	if (getenv("CCACHE_NOCOMPRESS")) {
+		mode = COPY_UNCOMPRESSED;
+	}
+
+	/* open source file */
+	fd_in = open(src, O_RDONLY);
+	if (fd_in == -1) {
+		return -1;
+	}
+
+	gz_in = gzdopen(fd_in, "rb");
+	if (!gz_in) {
+		close(fd_in);
+		return -1;
+	}
+
+	/* open destination file */
+	fd_out = mkstemp(tmp_name);
+	if (fd_out == -1) {
+		gzclose(gz_in);
+		free(tmp_name);
+		return -1;
+	}
+
+	if (mode == COPY_TO_CACHE) {
+		/* The gzip file format occupies at least 20 bytes. So
+		   it will always occupy an entire filesystem block,
+		   even for empty files.
+		   Since most stderr files will be empty, we turn off
+		   compression in this case to save space.
+		*/
+		if (fstat(fd_in, &st) != 0) {
+			gzclose(gz_in);
+			close(fd_out);
+			free(tmp_name);
+			return -1;
+		}
+		if (file_size(&st) == 0) {
+			mode = COPY_UNCOMPRESSED;
+		}
+	}
+
+	if (mode == COPY_TO_CACHE) {
+		gz_out = gzdopen(dup(fd_out), "wb");
+		if (!gz_out) {
+			gzclose(gz_in);
+			close(fd_out);
+			free(tmp_name);
+			return -1;
+		}
+	}
+
+	while ((n = gzread(gz_in, buf, sizeof(buf))) > 0) {
+		if (mode == COPY_TO_CACHE) {
+			ret = gzwrite(gz_out, buf, n);
+		} else {
+			ret = write(fd_out, buf, n);
+		}
+		if (ret != n) {
+			gzclose(gz_in);
+			if (gz_out) {
+				gzclose(gz_out);
+			}
+			close(fd_out);
+			unlink(tmp_name);
+			free(tmp_name);
+			return -1;
+		}
+	}
+
+	gzclose(gz_in);
+	if (gz_out) {
+		gzclose(gz_out);
+	}
+
+	/* get perms right on the tmp file */
+	mask = umask(0);
+	fchmod(fd_out, 0666 & ~mask);
+	umask(mask);
+
+	/* the close can fail on NFS if out of space */
+	if (close(fd_out) == -1) {
+		unlink(tmp_name);
+		free(tmp_name);
+		return -1;
+	}
+
+	unlink(dest);
+
+	if (rename(tmp_name, dest) == -1) {
+		unlink(tmp_name);
+		free(tmp_name);
+		return -1;
+	}
+
+	free(tmp_name);
+
+	return 0;
+}
+
+/* move a file to the cache, compressing it */
+int move_file(const char *src, const char *dest) {
+	int ret;
+
+	ret = _copy_file(src, dest, COPY_TO_CACHE);
+	if (ret != -1) unlink(src);
+	return ret;
+}
+
+/* copy a file to the cache, compressing it */
+static int copy_file_to_cache(const char *src, const char *dest) {
+	return _copy_file(src, dest, COPY_TO_CACHE);
+}
+
+/* copy a file from the cache, decompressing it */
+static int copy_file_from_cache(const char *src, const char *dest) {
+	return _copy_file(src, dest, COPY_FROM_CACHE);
+}
+#endif /* ENABLE_ZLIB */
+
+/* test if a file is zlib compressed */
+int test_if_compressed(const char *filename) {
+	FILE *f;
+
+	f = fopen(filename, "rb");
+	if (!f) {
+		return 0;
+	}
+
+	/* test if file starts with 1F8B, which is zlib's
+	 * magic number */
+	if ((fgetc(f) != 0x1f) || (fgetc(f) != 0x8b)) {
+		fclose(f);
+		return 0;
+	}
+	
+	fclose(f);
+	return 1;
+}
+
+/* copy file to the cache with error checking taking into account compression and hard linking if desired */
+int commit_to_cache(const char *src, const char *dest, int hardlink)
+{
+	int ret = -1;
+	struct stat st;
+	if (stat(src, &st) == 0) {
+		unlink(dest);
+		if (hardlink) {
+#ifdef _WIN32
+			ret = CreateHardLinkA(dest, src, NULL) ? 0 : -1;
+#else
+			ret = link(src, dest);
+#endif
+		}
+		if (ret == -1) {
+			ret = copy_file_to_cache(src, dest);
+			if (ret == -1) {
+				cc_log("failed to commit %s -> %s (%s)\n", src, dest, strerror(errno));
+				stats_update(STATS_ERROR);
+			}
+		}
+	} else {
+		cc_log("failed to put %s in the cache (%s)\n", src, strerror(errno));
+		stats_update(STATS_ERROR);
+	}
+	return ret;
+}
+
+/* copy file out of the cache with error checking taking into account compression and hard linking if desired */
+int retrieve_from_cache(const char *src, const char *dest, int hardlink)
+{
+	int ret = 0;
+
+	x_utimes(src);
+
+	if (strcmp(dest, "/dev/null") == 0) {
+		ret = 0;
+	} else {
+		unlink(dest);
+		/* only make a hardlink if the cache file is uncompressed */
+		if (hardlink && test_if_compressed(src) == 0) {
+#ifdef _WIN32
+			ret = CreateHardLinkA(dest, src, NULL) ? 0 : -1;
+#else
+			ret = link(src, dest);
+#endif
+		} else {
+			ret = copy_file_from_cache(src, dest);
+		}
+	}
+
+	/* the cached file might have been deleted by some external process */
+	if (ret == -1 && errno == ENOENT) {
+		cc_log("hashfile missing for %s\n", dest);
+		stats_update(STATS_MISSING);
+		return -1;
+	}
+
+	if (ret == -1) {
+		ret = copy_file_from_cache(src, dest);
+		if (ret == -1) {
+			cc_log("failed to retrieve %s -> %s (%s)\n", src, dest, strerror(errno));
+			stats_update(STATS_ERROR);
+			return -1;
+		}
+	}
+	return ret;
+}
+
+/* make sure a directory exists */
+int create_dir(const char *dir)
+{
+	struct stat st;
+	if (stat(dir, &st) == 0) {
+		if (S_ISDIR(st.st_mode)) {
+			return 0;
+		}
+		errno = ENOTDIR;
+		return 1;
+	}
+#ifdef _WIN32
+	if (mkdir(dir) != 0 && errno != EEXIST) {
+		return 1;
+	}
+#else
+	if (mkdir(dir, 0777) != 0 && errno != EEXIST) {
+		return 1;
+	}
+#endif
+	return 0;
+}
+
+char const CACHEDIR_TAG[] =
+	"Signature: 8a477f597d28d172789f06886806bc55\n"
+	"# This file is a cache directory tag created by ccache.\n"
+	"# For information about cache directory tags, see:\n"
+	"#	http://www.brynosaurus.com/cachedir/\n";
+
+int create_cachedirtag(const char *dir)
+{
+	char *filename;
+	struct stat st;
+	FILE *f;
+	x_asprintf(&filename, "%s/CACHEDIR.TAG", dir);
+	if (stat(filename, &st) == 0) {
+		if (S_ISREG(st.st_mode)) {
+			goto success;
+		}
+		errno = EEXIST;
+		goto error;
+	}
+	f = fopen(filename, "w");
+	if (!f) goto error;
+	if (fwrite(CACHEDIR_TAG, sizeof(CACHEDIR_TAG)-1, 1, f) != 1) {
+		goto error;
+	}
+	if (fclose(f)) goto error;
+success:
+	free(filename);
+	return 0;
+error:
+	free(filename);
+	return 1;
+}
+
+/*
+  this is like asprintf() but dies if the malloc fails
+  note that we use vsnprintf in a rather poor way to make this more portable
+*/
+void x_asprintf(char **ptr, const char *format, ...)
+{
+	va_list ap;
+
+	*ptr = NULL;
+	va_start(ap, format);
+	if (vasprintf(ptr, format, ap) == -1) {
+		fatal("out of memory in x_asprintf");
+	}
+	va_end(ap);
+	
+	if (!ptr) fatal("out of memory in x_asprintf");
+}
+
+/*
+  this is like strdup() but dies if the malloc fails
+*/
+char *x_strdup(const char *s)
+{
+	char *ret;
+	ret = strdup(s);
+	if (!ret) {
+		fatal("out of memory in strdup\n");
+	}
+	return ret;
+}
+
+/*
+  this is like malloc() but dies if the malloc fails
+*/
+void *x_malloc(size_t size)
+{
+	void *ret;
+	ret = malloc(size);
+	if (!ret) {
+		fatal("out of memory in malloc\n");
+	}
+	return ret;
+}
+
+/*
+  this is like realloc() but dies if the malloc fails
+*/
+void *x_realloc(void *ptr, size_t size)
+{
+	void *p2;
+#if 1
+	/* Avoid invalid read in memcpy below */
+	p2 = realloc(ptr, size);
+	if (!p2) {
+		fatal("out of memory in x_realloc");
+	}
+#else
+	if (!ptr) return x_malloc(size);
+	p2 = malloc(size);
+	if (!p2) {
+		fatal("out of memory in x_realloc");
+	}
+	if (ptr) {
+		/* Note invalid read as the memcpy reads beyond the memory allocated by ptr */
+		memcpy(p2, ptr, size);
+		free(ptr);
+	}
+#endif
+	return p2;
+}
+
+
+/* 
+   revsusive directory traversal - used for cleanup
+   fn() is called on all files/dirs in the tree
+ */
+void traverse(const char *dir, void (*fn)(const char *, struct stat *))
+{
+	DIR *d;
+	struct dirent *de;
+
+	d = opendir(dir);
+	if (!d) return;
+
+	while ((de = readdir(d))) {
+		char *fname;
+		struct stat st;
+
+		if (strcmp(de->d_name,".") == 0) continue;
+		if (strcmp(de->d_name,"..") == 0) continue;
+
+		if (strlen(de->d_name) == 0) continue;
+
+		x_asprintf(&fname, "%s/%s", dir, de->d_name);
+#ifdef _WIN32
+		if (stat(fname, &st))
+#else
+ 		if (lstat(fname, &st))
+#endif
+                {
+			if (errno != ENOENT) {
+				perror(fname);
+			}
+			free(fname);
+			continue;
+		}
+
+		if (S_ISDIR(st.st_mode)) {
+			traverse(fname, fn);
+		}
+
+		fn(fname, &st);
+		free(fname);
+	}
+
+	closedir(d);
+}
+
+
+/* return the base name of a file - caller frees */
+char *str_basename(const char *s)
+{
+	char *p = strrchr(s, '/');
+	if (p) {
+		s = (p+1);
+	}
+
+#ifdef _WIN32
+	p = strrchr(s, '\\');
+
+	if (p) {
+		s = (p+1);
+	}
+#endif
+
+	return x_strdup(s);
+}
+
+/* return the dir name of a file - caller frees */
+char *dirname(char *s)
+{
+	char *p;
+	s = x_strdup(s);
+	p = strrchr(s, '/');
+#ifdef _WIN32
+	p = strrchr(s, '\\');
+#endif
+	if (p) {
+		*p = 0;
+	} 
+	return s;
+}
+
+/*
+  http://www.ecst.csuchico.edu/~beej/guide/ipc/flock.html
+  http://cvs.php.net/viewvc.cgi/php-src/win32/flock.c?revision=1.2&view=markup
+  Should return 0 for success, >0 otherwise
+ */
+int lock_fd(int fd)
+{
+#ifdef _WIN32
+#  if 1
+	return _locking(fd, _LK_NBLCK, 1);
+#  else
+	HANDLE fl = (HANDLE)_get_osfhandle(fd);
+	OVERLAPPED o;
+	memset(&o, 0, sizeof(o));
+	return (LockFileEx(fl, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &o))
+		? 0 : GetLastError();
+#  endif
+#else
+	struct flock fl;
+	int ret;
+
+	fl.l_type = F_WRLCK;
+	fl.l_whence = SEEK_SET;
+	fl.l_start = 0;
+	fl.l_len = 1;
+	fl.l_pid = 0;
+
+	/* not sure why we would be getting a signal here,
+	   but one user claimed it is possible */
+	do {
+		ret = fcntl(fd, F_SETLKW, &fl);
+	} while (ret == -1 && errno == EINTR);
+	return ret;
+#endif
+}
+
+/* return size on disk of a file */
+size_t file_size(struct stat *st)
+{
+#ifdef _WIN32
+	return (st->st_size + 1023) & ~1023;
+#else
+	size_t size = st->st_blocks * 512;
+	if ((size_t)st->st_size > size) {
+		/* probably a broken stat() call ... */
+		size = (st->st_size + 1023) & ~1023;
+	}
+	return size;
+#endif
+}
+
+
+/* a safe open/create for read-write */
+int safe_open(const char *fname)
+{
+	int fd = open(fname, O_RDWR|O_BINARY);
+	if (fd == -1 && errno == ENOENT) {
+		fd = open(fname, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0666);
+		if (fd == -1 && errno == EEXIST) {
+			fd = open(fname, O_RDWR|O_BINARY);
+		}
+	}
+	return fd;
+}
+
+/* display a kilobyte unsigned value in M, k or G */
+void display_size(unsigned v)
+{
+	if (v > 1024*1024) {
+		printf("%8.1f Gbytes", v/((double)(1024*1024)));
+	} else if (v > 1024) {
+		printf("%8.1f Mbytes", v/((double)(1024)));
+	} else {
+		printf("%8u Kbytes", v);
+	}
+}
+
+/* return a value in multiples of 1024 give a string that can end
+   in K, M or G
+*/
+size_t value_units(const char *s)
+{
+	char m;
+	double v = atof(s);
+	m = s[strlen(s)-1];
+	switch (m) {
+	case 'G':
+	case 'g':
+	default:
+		v *= 1024*1024;
+		break;
+	case 'M':
+	case 'm':
+		v *= 1024;
+		break;
+	case 'K':
+	case 'k':
+		v *= 1;
+		break;
+	}
+	return (size_t)v;
+}
+
+
+/*
+  a sane realpath() function, trying to cope with stupid path limits and 
+  a broken API
+*/
+char *x_realpath(const char *path)
+{
+#ifdef _WIN32
+	char namebuf[MAX_PATH];
+	DWORD ret;
+
+	ret = GetFullPathNameA(path, sizeof(namebuf), namebuf, NULL);
+	if (ret == 0 || ret >= sizeof(namebuf)) {
+		return NULL;
+	}
+
+	return x_strdup(namebuf);
+#else
+	int maxlen;
+	char *ret, *p;
+#ifdef PATH_MAX
+	maxlen = PATH_MAX;
+#elif defined(MAXPATHLEN)
+	maxlen = MAXPATHLEN;
+#elif defined(_PC_PATH_MAX)
+	maxlen = pathconf(path, _PC_PATH_MAX);
+#endif
+	if (maxlen < 4096) maxlen = 4096;
+	
+	ret = x_malloc(maxlen);
+
+#if HAVE_REALPATH
+	p = realpath(path, ret);
+#else
+	/* yes, there are such systems. This replacement relies on
+	   the fact that when we call x_realpath we only care about symlinks */
+	{
+		int len = readlink(path, ret, maxlen-1);
+		if (len == -1) {
+			free(ret);
+			return NULL;
+		}
+		ret[len] = 0;
+		p = ret;
+	}
+#endif
+	if (p) {
+		p = x_strdup(p);
+		free(ret);
+		return p;
+	}
+	free(ret);
+	return NULL;
+#endif
+}
+
+/* a getcwd that will returns an allocated buffer */
+char *gnu_getcwd(void)
+{
+	unsigned size = 128;
+
+	while (1) {
+		char *buffer = (char *)x_malloc(size);
+		if (getcwd(buffer, size) == buffer) {
+			return buffer;
+		}
+		free(buffer);
+		if (errno != ERANGE) {
+			return 0;
+		}
+		size *= 2;
+	}
+}
+
+/* create an empty file */
+int create_empty_file(const char *fname)
+{
+	int fd;
+
+	fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
+	if (fd == -1) {
+		return -1;
+	}
+	close(fd);
+	return 0;
+}
+
+/*
+  return current users home directory or die
+*/
+const char *get_home_directory(void)
+{
+#ifdef _WIN32
+	static char home_path[MAX_PATH] = {0};
+	HRESULT ret;
+
+	/* we already have the path */
+	if (home_path[0] != 0) {
+		return home_path;
+	}
+
+	/* get the path to "Application Data" folder */
+	ret = SHGetFolderPathA(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, home_path);
+	if (SUCCEEDED(ret)) {
+		return home_path;
+	}
+
+	fprintf(stderr, "ccache: Unable to determine home directory\n");
+	return NULL;
+#else
+	const char *p = getenv("HOME");
+	if (p) {
+		return p;
+	}
+#ifdef HAVE_GETPWUID
+	{
+		struct passwd *pwd = getpwuid(getuid());
+		if (pwd) {
+			return pwd->pw_dir;
+		}
+	}
+#endif
+	fatal("Unable to determine home directory");
+	return NULL;
+#endif
+}
+
+int x_utimes(const char *filename)
+{
+#ifdef HAVE_UTIMES
+	return utimes(filename, NULL);
+#else
+	return utime(filename, NULL);
+#endif
+}
+
+#ifdef _WIN32
+/* perror for Win32 API calls, using GetLastError() instead of errno */
+void perror_win32(LPTSTR pszFunction)
+{
+	LPTSTR pszMessage;
+	DWORD dwLastError = GetLastError();
+
+	FormatMessage(	FORMAT_MESSAGE_ALLOCATE_BUFFER |
+			FORMAT_MESSAGE_FROM_SYSTEM |
+			FORMAT_MESSAGE_IGNORE_INSERTS,
+			NULL,
+			dwLastError,
+			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+			(LPTSTR)&pszMessage,
+			0, NULL );
+
+	fprintf(stderr, "%s: %s\n", pszFunction, pszMessage);
+	LocalFree(pszMessage);
+}
+#endif