⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 util.c

📁 Rsync 3.0.5 source code
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* If no --partial-dir option was specified, we don't need to do anything * (the partial-dir is essentially '.'), so just return success. */int handle_partial_dir(const char *fname, int create){	char *fn, *dir;	if (fname != partial_fname)		return 1;	if (!create && *partial_dir == '/')		return 1;	if (!(fn = strrchr(partial_fname, '/')))		return 1;	*fn = '\0';	dir = partial_fname;	if (create) {		STRUCT_STAT st;		int statret = do_lstat(dir, &st);		if (statret == 0 && !S_ISDIR(st.st_mode)) {			if (do_unlink(dir) < 0) {				*fn = '/';				return 0;			}			statret = -1;		}		if (statret < 0 && do_mkdir(dir, 0700) < 0) {			*fn = '/';			return 0;		}	} else		do_rmdir(dir);	*fn = '/';	return 1;}/** * Determine if a symlink points outside the current directory tree. * This is considered "unsafe" because e.g. when mirroring somebody * else's machine it might allow them to establish a symlink to * /etc/passwd, and then read it through a web server. * * Null symlinks and absolute symlinks are always unsafe. * * Basically here we are concerned with symlinks whose target contains * "..", because this might cause us to walk back up out of the * transferred directory.  We are not allowed to go back up and * reenter. * * @param dest Target of the symlink in question. * * @param src Top source directory currently applicable.  Basically this * is the first parameter to rsync in a simple invocation, but it's * modified by flist.c in slightly complex ways. * * @retval True if unsafe * @retval False is unsafe * * @sa t_unsafe.c **/int unsafe_symlink(const char *dest, const char *src){	const char *name, *slash;	int depth = 0;	/* all absolute and null symlinks are unsafe */	if (!dest || !*dest || *dest == '/')		return 1;	/* find out what our safety margin is */	for (name = src; (slash = strchr(name, '/')) != 0; name = slash+1) {		if (strncmp(name, "../", 3) == 0) {			depth = 0;		} else if (strncmp(name, "./", 2) == 0) {			/* nothing */		} else {			depth++;		}	}	if (strcmp(name, "..") == 0)		depth = 0;	for (name = dest; (slash = strchr(name, '/')) != 0; name = slash+1) {		if (strncmp(name, "../", 3) == 0) {			/* if at any point we go outside the current directory			   then stop - it is unsafe */			if (--depth < 0)				return 1;		} else if (strncmp(name, "./", 2) == 0) {			/* nothing */		} else {			depth++;		}	}	if (strcmp(name, "..") == 0)		depth--;	return (depth < 0);}#define HUMANIFY(mult) \	do { \		if (num >= mult || num <= -mult) { \			double dnum = (double)num / mult; \			char units; \			if (num < 0) \				dnum = -dnum; \			if (dnum < mult) \				units = 'K'; \			else if ((dnum /= mult) < mult) \				units = 'M'; \			else { \				dnum /= mult; \				units = 'G'; \			} \			if (num < 0) \				dnum = -dnum; \			snprintf(bufs[n], sizeof bufs[0], "%.2f%c", dnum, units); \			return bufs[n]; \		} \	} while (0)/* Return the int64 number as a string.  If the --human-readable option was * specified, we may output the number in K, M, or G units.  We can return * up to 4 buffers at a time. */char *human_num(int64 num){	static char bufs[4][128]; /* more than enough room */	static unsigned int n;	char *s;	int negated;	n = (n + 1) % (sizeof bufs / sizeof bufs[0]);	if (human_readable) {		if (human_readable == 1)			HUMANIFY(1000);		else			HUMANIFY(1024);	}	s = bufs[n] + sizeof bufs[0] - 1;	*s = '\0';	if (!num)		*--s = '0';	if (num < 0) {		/* A maximum-size negated number can't fit as a positive,		 * so do one digit in negated form to start us off. */		*--s = (char)(-(num % 10)) + '0';		num = -(num / 10);		negated = 1;	} else		negated = 0;	while (num) {		*--s = (char)(num % 10) + '0';		num /= 10;	}	if (negated)		*--s = '-';	return s;}/* Return the double number as a string.  If the --human-readable option was * specified, we may output the number in K, M, or G units.  We use a buffer * from human_num() to return our result. */char *human_dnum(double dnum, int decimal_digits){	char *buf = human_num(dnum);	int len = strlen(buf);	if (isDigit(buf + len - 1)) {		/* There's extra room in buf prior to the start of the num. */		buf -= decimal_digits + 2;		snprintf(buf, len + decimal_digits + 3, "%.*f", decimal_digits, dnum);	}	return buf;}/* Return the date and time as a string.  Some callers tweak returned buf. */char *timestring(time_t t){	static char TimeBuf[200];	struct tm *tm = localtime(&t);	char *p;#ifdef HAVE_STRFTIME	strftime(TimeBuf, sizeof TimeBuf - 1, "%Y/%m/%d %H:%M:%S", tm);#else	strlcpy(TimeBuf, asctime(tm), sizeof TimeBuf);#endif	if ((p = strchr(TimeBuf, '\n')) != NULL)		*p = '\0';	return TimeBuf;}/** * Sleep for a specified number of milliseconds. * * Always returns TRUE.  (In the future it might return FALSE if * interrupted.) **/int msleep(int t){	int tdiff = 0;	struct timeval tval, t1, t2;	gettimeofday(&t1, NULL);	while (tdiff < t) {		tval.tv_sec = (t-tdiff)/1000;		tval.tv_usec = 1000*((t-tdiff)%1000);		errno = 0;		select(0,NULL,NULL, NULL, &tval);		gettimeofday(&t2, NULL);		tdiff = (t2.tv_sec - t1.tv_sec)*1000 +			(t2.tv_usec - t1.tv_usec)/1000;	}	return True;}/* Determine if two time_t values are equivalent (either exact, or in * the modification timestamp window established by --modify-window). * * @retval 0 if the times should be treated as the same * * @retval +1 if the first is later * * @retval -1 if the 2nd is later **/int cmp_time(time_t file1, time_t file2){	if (file2 > file1) {		if (file2 - file1 <= modify_window)			return 0;		return -1;	}	if (file1 - file2 <= modify_window)		return 0;	return 1;}#ifdef __INSURE__XX#include <dlfcn.h>/**   This routine is a trick to immediately catch errors when debugging   with insure. A xterm with a gdb is popped up when insure catches   a error. It is Linux specific.**/int _Insure_trap_error(int a1, int a2, int a3, int a4, int a5, int a6){	static int (*fn)();	int ret;	char *cmd;	asprintf(&cmd, "/usr/X11R6/bin/xterm -display :0 -T Panic -n Panic -e /bin/sh -c 'cat /tmp/ierrs.*.%d ; gdb /proc/%d/exe %d'",		getpid(), getpid(), getpid());	if (!fn) {		static void *h;		h = dlopen("/usr/local/parasoft/insure++lite/lib.linux2/libinsure.so", RTLD_LAZY);		fn = dlsym(h, "_Insure_trap_error");	}	ret = fn(a1, a2, a3, a4, a5, a6);	system(cmd);	free(cmd);	return ret;}#endif#define MALLOC_MAX 0x40000000void *_new_array(unsigned long num, unsigned int size, int use_calloc){	if (num >= MALLOC_MAX/size)		return NULL;	return use_calloc ? calloc(num, size) : malloc(num * size);}void *_realloc_array(void *ptr, unsigned int size, size_t num){	if (num >= MALLOC_MAX/size)		return NULL;	if (!ptr)		return malloc(size * num);	return realloc(ptr, size * num);}/* Take a filename and filename length and return the most significant * filename suffix we can find.  This ignores suffixes such as "~", * ".bak", ".orig", ".~1~", etc. */const char *find_filename_suffix(const char *fn, int fn_len, int *len_ptr){	const char *suf, *s;	BOOL had_tilde;	int s_len;	/* One or more dots at the start aren't a suffix. */	while (fn_len && *fn == '.') fn++, fn_len--;	/* Ignore the ~ in a "foo~" filename. */	if (fn_len > 1 && fn[fn_len-1] == '~')		fn_len--, had_tilde = True;	else		had_tilde = False;	/* Assume we don't find an suffix. */	suf = "";	*len_ptr = 0;	/* Find the last significant suffix. */	for (s = fn + fn_len; fn_len > 1; ) {		while (*--s != '.' && s != fn) {}		if (s == fn)			break;		s_len = fn_len - (s - fn);		fn_len = s - fn;		if (s_len == 4) {			if (strcmp(s+1, "bak") == 0			 || strcmp(s+1, "old") == 0)				continue;		} else if (s_len == 5) {			if (strcmp(s+1, "orig") == 0)				continue;		} else if (s_len > 2 && had_tilde		    && s[1] == '~' && isDigit(s + 2))			continue;		*len_ptr = s_len;		suf = s;		if (s_len == 1)			break;		/* Determine if the suffix is all digits. */		for (s++, s_len--; s_len > 0; s++, s_len--) {			if (!isDigit(s))				return suf;		}		/* An all-digit suffix may not be that signficant. */		s = suf;	}	return suf;}/* This is an implementation of the Levenshtein distance algorithm.  It * was implemented to avoid needing a two-dimensional matrix (to save * memory).  It was also tweaked to try to factor in the ASCII distance * between changed characters as a minor distance quantity.  The normal * Levenshtein units of distance (each signifying a single change between * the two strings) are defined as a "UNIT". */#define UNIT (1 << 16)uint32 fuzzy_distance(const char *s1, int len1, const char *s2, int len2){	uint32 a[MAXPATHLEN], diag, above, left, diag_inc, above_inc, left_inc;	int32 cost;	int i1, i2;	if (!len1 || !len2) {		if (!len1) {			s1 = s2;			len1 = len2;		}		for (i1 = 0, cost = 0; i1 < len1; i1++)			cost += s1[i1];		return (int32)len1 * UNIT + cost;	}	for (i2 = 0; i2 < len2; i2++)		a[i2] = (i2+1) * UNIT;	for (i1 = 0; i1 < len1; i1++) {		diag = i1 * UNIT;		above = (i1+1) * UNIT;		for (i2 = 0; i2 < len2; i2++) {			left = a[i2];			if ((cost = *((uchar*)s1+i1) - *((uchar*)s2+i2)) != 0) {				if (cost < 0)					cost = UNIT - cost;				else					cost = UNIT + cost;			}			diag_inc = diag + cost;			left_inc = left + UNIT + *((uchar*)s1+i1);			above_inc = above + UNIT + *((uchar*)s2+i2);			a[i2] = above = left < above			      ? (left_inc < diag_inc ? left_inc : diag_inc)			      : (above_inc < diag_inc ? above_inc : diag_inc);			diag = left;		}	}	return a[len2-1];}#define BB_SLOT_SIZE     (16*1024)          /* Desired size in bytes */#define BB_PER_SLOT_BITS (BB_SLOT_SIZE * 8) /* Number of bits per slot */#define BB_PER_SLOT_INTS (BB_SLOT_SIZE / 4) /* Number of int32s per slot */struct bitbag {    uint32 **bits;    int slot_cnt;};struct bitbag *bitbag_create(int max_ndx){	struct bitbag *bb = new(struct bitbag);	bb->slot_cnt = (max_ndx + BB_PER_SLOT_BITS - 1) / BB_PER_SLOT_BITS;	if (!(bb->bits = (uint32**)calloc(bb->slot_cnt, sizeof (uint32*))))		out_of_memory("bitbag_create");	return bb;}void bitbag_set_bit(struct bitbag *bb, int ndx){	int slot = ndx / BB_PER_SLOT_BITS;	ndx %= BB_PER_SLOT_BITS;	if (!bb->bits[slot]) {		if (!(bb->bits[slot] = (uint32*)calloc(BB_PER_SLOT_INTS, 4)))			out_of_memory("bitbag_set_bit");	}	bb->bits[slot][ndx/32] |= 1u << (ndx % 32);}#if 0 /* not needed yet */void bitbag_clear_bit(struct bitbag *bb, int ndx){	int slot = ndx / BB_PER_SLOT_BITS;	ndx %= BB_PER_SLOT_BITS;	if (!bb->bits[slot])		return;	bb->bits[slot][ndx/32] &= ~(1u << (ndx % 32));}int bitbag_check_bit(struct bitbag *bb, int ndx){	int slot = ndx / BB_PER_SLOT_BITS;	ndx %= BB_PER_SLOT_BITS;	if (!bb->bits[slot])		return 0;	return bb->bits[slot][ndx/32] & (1u << (ndx % 32)) ? 1 : 0;}#endif/* Call this with -1 to start checking from 0.  Returns -1 at the end. */int bitbag_next_bit(struct bitbag *bb, int after){	uint32 bits, mask;	int i, ndx = after + 1;	int slot = ndx / BB_PER_SLOT_BITS;	ndx %= BB_PER_SLOT_BITS;	mask = (1u << (ndx % 32)) - 1;	for (i = ndx / 32; slot < bb->slot_cnt; slot++, i = mask = 0) {		if (!bb->bits[slot])			continue;		for ( ; i < BB_PER_SLOT_INTS; i++, mask = 0) {			if (!(bits = bb->bits[slot][i] & ~mask))				continue;			/* The xor magic figures out the lowest enabled bit in			 * bits, and the switch quickly computes log2(bit). */			switch (bits ^ (bits & (bits-1))) {#define LOG2(n) case 1u << n: return slot*BB_PER_SLOT_BITS + i*32 + n			    LOG2(0);  LOG2(1);  LOG2(2);  LOG2(3);			    LOG2(4);  LOG2(5);  LOG2(6);  LOG2(7);			    LOG2(8);  LOG2(9);  LOG2(10); LOG2(11);			    LOG2(12); LOG2(13); LOG2(14); LOG2(15);			    LOG2(16); LOG2(17); LOG2(18); LOG2(19);			    LOG2(20); LOG2(21); LOG2(22); LOG2(23);			    LOG2(24); LOG2(25); LOG2(26); LOG2(27);			    LOG2(28); LOG2(29); LOG2(30); LOG2(31);			}			return -1; /* impossible... */		}	}	return -1;}void flist_ndx_push(flist_ndx_list *lp, int ndx){	struct flist_ndx_item *item;	if (!(item = new(struct flist_ndx_item)))		out_of_memory("flist_ndx_push");	item->next = NULL;	item->ndx = ndx;	if (lp->tail)		lp->tail->next = item;	else		lp->head = item;	lp->tail = item;}int flist_ndx_pop(flist_ndx_list *lp){	struct flist_ndx_item *next;	int ndx;	if (!lp->head)		return -1;	ndx = lp->head->ndx;	next = lp->head->next;	free(lp->head);	lp->head = next;	if (!next)		lp->tail = NULL;	return ndx;}void *expand_item_list(item_list *lp, size_t item_size,		       const char *desc, int incr){	/* First time through, 0 <= 0, so list is expanded. */	if (lp->malloced <= lp->count) {		void *new_ptr;		size_t new_size = lp->malloced;		if (incr < 0)			new_size += -incr; /* increase slowly */		else if (new_size < (size_t)incr)			new_size += incr;		else			new_size *= 2;		if (new_size < lp->malloced)			overflow_exit("expand_item_list");		/* Using _realloc_array() lets us pass the size, not a type. */		new_ptr = _realloc_array(lp->items, item_size, new_size);		if (verbose >= 4) {			rprintf(FINFO, "[%s] expand %s to %.0f bytes, did%s move\n",				who_am_i(), desc, (double)new_size * item_size,				new_ptr == lp->items ? " not" : "");		}		if (!new_ptr)			out_of_memory("expand_item_list");		lp->items = new_ptr;		lp->malloced = new_size;	}	return (char*)lp->items + (lp->count++ * item_size);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -