1 /*
2  * Schism Tracker - a cross-platform Impulse Tracker clone
3  * copyright (c) 2003-2005 Storlek <storlek@rigelseven.com>
4  * copyright (c) 2005-2008 Mrs. Brisby <mrs.brisby@nimh.org>
5  * copyright (c) 2009 Storlek & Mrs. Brisby
6  * copyright (c) 2010-2012 Storlek
7  * URL: http://schismtracker.org/
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 /* This is just a collection of some useful functions. None of these use any
25 extraneous libraries (i.e. GLib). */
26 
27 
28 #define NEED_DIRENT
29 #define NEED_TIME
30 #include "headers.h"
31 
32 #include "util.h"
33 #include "osdefs.h" /* need this for win32_filecreated_callback */
34 
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 
38 #include <errno.h>
39 
40 #include <stdarg.h>
41 
42 #include <math.h>
43 
44 #if defined(__amigaos4__)
45 # define FALLBACK_DIR "." /* not used... */
46 #elif defined(WIN32)
47 # define FALLBACK_DIR "C:\\"
48 #elif defined(GEKKO)
49 # define FALLBACK_DIR "isfs:/" // always exists, seldom useful
50 #else /* POSIX? */
51 # define FALLBACK_DIR "/"
52 #endif
53 
54 #ifdef WIN32
55 #include <windows.h>
56 #include <process.h>
57 #include <shlobj.h>
58 #else
59 #include <sys/types.h>
60 #include <sys/wait.h>
61 #endif
62 
63 void ms_sleep(unsigned int ms)
64 {
65 #ifdef WIN32
66 	SleepEx(ms,FALSE);
67 #else
68 	usleep(ms*1000);
69 #endif
70 }
71 
72 char *str_dup(const char *s)
73 {
74 	char *q;
75 	q = strdup(s);
76 	if (!q) {
77 		/* throw out of memory exception */
78 		perror("strdup");
79 		exit(255);
80 	}
81 	return q;
82 }
83 
84 char *strn_dup(const char *s, size_t n)
85 {
86 	char *q;
87 	q = malloc(n + 1);
88 	if (!q) {
89 		/* throw out of memory exception */
90 		perror("strndup");
91 		exit(255);
92 	}
93 	memcpy(q, s, n);
94 	q[n] = '\0';
95 	return q;
96 }
97 
98 void *mem_alloc(size_t amount)
99 {
100 	void *q;
101 	q = malloc(amount);
102 	if (!q) {
103 		/* throw out of memory exception */
104 		perror("malloc");
105 		exit(255);
106 	}
107 	return q;
108 }
109 
110 void *mem_calloc(size_t nmemb, size_t size)
111 {
112 	void *q;
113 	q = calloc(nmemb, size);
114 	if (!q) {
115 		/* throw out of memory exception */
116 		perror("calloc");
117 		exit(255);
118 	}
119 	return q;
120 }
121 
122 void *mem_realloc(void *orig, size_t amount)
123 {
124 	void *q;
125 	if (!orig) return mem_alloc(amount);
126 	q = realloc(orig, amount);
127 	if (!q) {
128 		/* throw out of memory exception */
129 		perror("malloc");
130 		exit(255);
131 	}
132 	return q;
133 }
134 
135 
136 /* --------------------------------------------------------------------- */
137 /* CONVERSION FUNCTIONS */
138 
139 /* linear -> deciBell */
140 /* amplitude normalized to 1.0f. */
141 float dB(float amplitude)
142 {
143 	return 20.0f * log10f(amplitude);
144 }
145 
146 /* deciBell -> linear */
147 float dB2_amp(float db)
148 {
149 	return powf(10.0f, db / 20.0f);
150 }
151 
152 /* linear -> deciBell */
153 /* power normalized to 1.0f. */
154 float pdB(float power)
155 {
156 	return 10.0f * log10f(power);
157 }
158 
159 /* deciBell -> linear */
160 float dB2_power(float db)
161 {
162 	return powf(10.0f, db / 10.0f);
163 }
164 /* linear -> deciBell */
165 /* amplitude normalized to 1.0f. */
166 /* Output scaled (and clipped) to 128 lines with noisefloor range. */
167 /* ([0..128] = [-noisefloor..0dB]) */
168 /* correction_dBs corrects the dB after converted, but before scaling.*/
169 short dB_s(int noisefloor, float amplitude, float correction_dBs)
170 {
171 	float db = dB(amplitude) + correction_dBs;
172 	return CLAMP((int)(128.f*(db+noisefloor))/noisefloor, 0, 127);
173 }
174 
175 /* deciBell -> linear */
176 /* Input scaled to 128 lines with noisefloor range. */
177 /* ([0..128] = [-noisefloor..0dB]) */
178 /* amplitude normalized to 1.0f. */
179 /* correction_dBs corrects the dB after converted, but before scaling.*/
180 short dB2_amp_s(int noisefloor, int db, float correction_dBs)
181 {
182 	return dB2_amp((db*noisefloor/128.f)-noisefloor-correction_dBs);
183 }
184 /* linear -> deciBell */
185 /* power normalized to 1.0f. */
186 /* Output scaled (and clipped) to 128 lines with noisefloor range. */
187 /* ([0..128] = [-noisefloor..0dB]) */
188 /* correction_dBs corrects the dB after converted, but before scaling.*/
189 short pdB_s(int noisefloor, float power, float correction_dBs)
190 {
191 	float db = pdB(power)+correction_dBs;
192 	return CLAMP((int)(128.f*(db+noisefloor))/noisefloor, 0, 127);
193 }
194 
195 /* deciBell -> linear */
196 /* Input scaled to 128 lines with noisefloor range. */
197 /* ([0..128] = [-noisefloor..0dB]) */
198 /* power normalized to 1.0f. */
199 /* correction_dBs corrects the dB after converted, but before scaling.*/
200 short dB2_power_s(int noisefloor, int db, float correction_dBs)
201 {
202 	return dB2_power((db*noisefloor/128.f)-noisefloor-correction_dBs);
203 }
204 /* --------------------------------------------------------------------- */
205 /* FORMATTING FUNCTIONS */
206 
207 char *get_date_string(time_t when, char *buf)
208 {
209 	struct tm tmr;
210 	const char *month_str[12] = {
211 		"January",
212 		"February",
213 		"March",
214 		"April",
215 		"May",
216 		"June",
217 		"July",
218 		"August",
219 		"September",
220 		"October",
221 		"November",
222 		"December",
223 	};
224 
225 	/* DO NOT change this back to localtime(). If some backward platform
226 	doesn't have localtime_r, it needs to be implemented separately. */
227 	localtime_r(&when, &tmr);
228 	snprintf(buf, 27, "%s %d, %d", month_str[tmr.tm_mon], tmr.tm_mday, 1900 + tmr.tm_year);
229 	return buf;
230 }
231 
232 char *get_time_string(time_t when, char *buf)
233 {
234 	struct tm tmr;
235 
236 	localtime_r(&when, &tmr);
237 	snprintf(buf, 27, "%d:%02d%s", tmr.tm_hour % 12 ? : 12, tmr.tm_min, tmr.tm_hour < 12 ? "am" : "pm");
238 	return buf;
239 }
240 
241 char *num99tostr(int n, char *buf)
242 {
243 	static const char *qv = "HIJKLMNOPQRSTUVWXYZ";
244 	if (n < 100) {
245 		sprintf(buf, "%02d", n);
246 	} else if (n <= 256) {
247 		n -= 100;
248 		sprintf(buf, "%c%d",
249 			qv[(n/10)], (n % 10));
250 	}
251 	return buf;
252 
253 }
254 char *numtostr(int digits, unsigned int n, char *buf)
255 {
256 	if (digits > 0) {
257 		char fmt[] = "%03u";
258 
259 		digits %= 10;
260 		fmt[2] = '0' + digits;
261 		snprintf(buf, digits + 1, fmt, n);
262 		buf[digits] = 0;
263 	} else {
264 		sprintf(buf, "%u", n);
265 	}
266 	return buf;
267 }
268 char *numtostr_signed(int digits, int n, char *buf)
269 {
270 	if (digits > 0) {
271 		char fmt[] = "%03d";
272 
273 		digits %= 10;
274 		fmt[2] = '0' + digits;
275 		snprintf(buf, digits + 1, fmt, n);
276 		buf[digits] = 0;
277 	} else {
278 		sprintf(buf, "%d", n);
279 	}
280 	return buf;
281 }
282 
283 /* --------------------------------------------------------------------- */
284 /* STRING HANDLING FUNCTIONS */
285 
286 /* I was intending to get rid of this and use glibc's basename() instead,
287 but it doesn't do what I want (i.e. not bother with the string) and thanks
288 to the stupid libgen.h basename that's totally different, it'd cause some
289 possible portability issues. */
290 const char *get_basename(const char *filename)
291 {
292 	const char *base = strrchr(filename, DIR_SEPARATOR);
293 	if (base) {
294 		/* skip the slash */
295 		base++;
296 	}
297 	if (!(base && *base)) {
298 		/* well, there isn't one, so just return the filename */
299 		base = filename;
300 	}
301 
302 	return base;
303 }
304 
305 const char *get_extension(const char *filename)
306 {
307 	filename = get_basename(filename);
308 
309 	const char *extension = strrchr(filename, '.');
310 	if (!extension) {
311 		/* no extension? bummer. point to the \0 at the end of the string. */
312 		extension = strchr(filename, '\0');
313 	}
314 
315 	return extension;
316 }
317 
318 char *get_parent_directory(const char *dirname)
319 {
320 	char *ret, *pos;
321 	int n;
322 
323 	if (!dirname || !dirname[0])
324 		return NULL;
325 
326 	ret = str_dup(dirname);
327 	if (!ret)
328 		return NULL;
329 	n = strlen(ret) - 1;
330 	if (ret[n] == DIR_SEPARATOR)
331 		ret[n] = 0;
332 	pos = strrchr(ret, DIR_SEPARATOR);
333 	if (!pos) {
334 		free(ret);
335 		return NULL;
336 	}
337 	pos[1] = 0;
338 	return ret;
339 }
340 
341 static const char *whitespace = " \t\v\r\n";
342 
343 inline int ltrim_string(char *s)
344 {
345 	int ws = strspn(s, whitespace);
346 	int len = strlen(s) - ws;
347 
348 	if (ws)
349 		memmove(s, s + ws, len + 1);
350 	return len;
351 }
352 
353 inline int rtrim_string(char *s)
354 {
355 	int len = strlen(s) - 1;
356 
357 	while (len > 0 && strchr(whitespace, s[len]))
358 		len--;
359 	len++;
360 	s[len] = '\0';
361 	return len;
362 }
363 
364 int trim_string(char *s)
365 {
366 	ltrim_string(s);
367 	return rtrim_string(s);
368 }
369 
370 
371 /* break the string 's' with the character 'c', placing the two parts in 'first' and 'second'.
372 return: 1 if the string contained the character (and thus could be split), 0 if not.
373 the pointers returned in first/second should be free()'d by the caller. */
374 int str_break(const char *s, char c, char **first, char **second)
375 {
376 	const char *p = strchr(s, c);
377 	if (!p)
378 		return 0;
379 	*first = mem_alloc(p - s + 1);
380 	strncpy(*first, s, p - s);
381 	(*first)[p - s] = 0;
382 	*second = str_dup(p + 1);
383 	return 1;
384 }
385 
386 /* adapted from glib. in addition to the normal c escapes, this also escapes the hashmark and semicolon
387  * (comment characters). if space is true, the first/last character is also escaped if it is a space. */
388 char *str_escape(const char *s, int space)
389 {
390 	/* Each source byte needs maximally four destination chars (\777) */
391 	char *dest = calloc(4 * strlen(s) + 1, sizeof(char));
392 	char *d = dest;
393 
394 	if (space && *s == ' ') {
395 		*d++ = '\\';
396 		*d++ = '0';
397 		*d++ = '4';
398 		*d++ = '0';
399 		s++;
400 	}
401 
402 	while (*s) {
403 		switch (*s) {
404 		case '\a':
405 			*d++ = '\\';
406 			*d++ = 'a';
407 			break;
408 		case '\b':
409 			*d++ = '\\';
410 			*d++ = 'b';
411 			break;
412 		case '\f':
413 			*d++ = '\\';
414 			*d++ = 'f';
415 			break;
416 		case '\n':
417 			*d++ = '\\';
418 			*d++ = 'n';
419 			break;
420 		case '\r':
421 			*d++ = '\\';
422 			*d++ = 'r';
423 			break;
424 		case '\t':
425 			*d++ = '\\';
426 			*d++ = 't';
427 			break;
428 		case '\v':
429 			*d++ = '\\';
430 			*d++ = 'v';
431 			break;
432 		case '\\': case '"':
433 			*d++ = '\\';
434 			*d++ = *s;
435 			break;
436 
437 		default:
438 			if (*s < ' ' || *s >= 127 || (space && *s == ' ' && s[1] == '\0')) {
439 		case '#': case ';':
440 				*d++ = '\\';
441 				*d++ = '0' + ((((uint8_t) *s) >> 6) & 7);
442 				*d++ = '0' + ((((uint8_t) *s) >> 3) & 7);
443 				*d++ = '0' + ( ((uint8_t) *s)       & 7);
444 			} else {
445 				*d++ = *s;
446 			}
447 			break;
448 		}
449 		s++;
450 	}
451 
452 	*d = 0;
453 	return dest;
454 }
455 
456 static inline int readhex(const char *s, int w)
457 {
458 	int o = 0;
459 
460 	while (w--) {
461 		o <<= 4;
462 		switch (*s) {
463 			case '0'...'9': o |= *s - '0';      break;
464 			case 'a'...'f': o |= *s - 'a' + 10; break;
465 			case 'A'...'F': o |= *s - 'A' + 10; break;
466 			default: return -1;
467 		}
468 		s++;
469 	}
470 	return o;
471 }
472 
473 /* opposite of str_escape. (this is glib's 'compress' function renamed more clearly) */
474 char *str_unescape(const char *s)
475 {
476 	const char *end;
477 	int hex;
478 	char *dest = calloc(strlen(s) + 1, sizeof(char));
479 	char *d = dest;
480 
481 	while (*s) {
482 		if (*s == '\\') {
483 			s++;
484 			switch (*s) {
485 			case '0'...'7':
486 				*d = 0;
487 				end = s + 3;
488 				while (s < end && *s >= '0' && *s <= '7') {
489 					*d = *d * 8 + *s - '0';
490 					s++;
491 				}
492 				d++;
493 				s--;
494 				break;
495 			case 'a':
496 				*d++ = '\a';
497 				break;
498 			case 'b':
499 				*d++ = '\b';
500 				break;
501 			case 'f':
502 				*d++ = '\f';
503 				break;
504 			case 'n':
505 				*d++ = '\n';
506 				break;
507 			case 'r':
508 				*d++ = '\r';
509 				break;
510 			case 't':
511 				*d++ = '\t';
512 				break;
513 			case 'v':
514 				*d++ = '\v';
515 				break;
516 			case '\0': // trailing backslash?
517 				*d++ = '\\';
518 				s--;
519 				break;
520 			case 'x':
521 				hex = readhex(s + 1, 2);
522 				if (hex >= 0) {
523 					*d++ = hex;
524 					s += 2;
525 					break;
526 				}
527 				/* fall through */
528 			default: /* Also handles any other char, like \" \\ \; etc. */
529 				*d++ = *s;
530 				break;
531 			}
532 		} else {
533 			*d++ = *s;
534 		}
535 		s++;
536 	}
537 	*d = 0;
538 
539 	return dest;
540 }
541 
542 char *pretty_name(const char *filename)
543 {
544 	char *ret, *temp;
545 	const char *ptr;
546 	int len;
547 
548 	ptr = strrchr(filename, DIR_SEPARATOR);
549 	ptr = ((ptr && ptr[1]) ? ptr + 1 : filename);
550 	len = strrchr(ptr, '.') - ptr;
551 	if (len <= 0) {
552 		ret = str_dup(ptr);
553 	} else {
554 		ret = calloc(len + 1, sizeof(char));
555 		strncpy(ret, ptr, len);
556 		ret[len] = 0;
557 	}
558 
559 	/* change underscores to spaces (of course, this could be adapted
560 	 * to use strpbrk and strip any number of characters) */
561 	while ((temp = strchr(ret, '_')) != NULL)
562 		*temp = ' ';
563 
564 	/* TODO | the first letter, and any letter following a space,
565 	 * TODO | should be capitalized; multiple spaces should be cut
566 	 * TODO | down to one */
567 
568 	trim_string(ret);
569 	return ret;
570 }
571 
572 /* blecch */
573 int get_num_lines(const char *text)
574 {
575 	const char *ptr = text;
576 	int n = 0;
577 
578 	if (!text)
579 		return 0;
580 	for (;;) {
581 		ptr = strpbrk(ptr, "\015\012");
582 		if (!ptr)
583 			return n;
584 		if (ptr[0] == 13 && ptr[1] == 10)
585 			ptr += 2;
586 		else
587 			ptr++;
588 		n++;
589 	}
590 }
591 
592 /* --------------------------------------------------------------------- */
593 /* FILE INFO FUNCTIONS */
594 
595 /* 0 = success, !0 = failed (check errno) */
596 int make_backup_file(const char *filename, int numbered)
597 {
598 	char buf[PATH_MAX];
599 
600 	/* ensure plenty of room to breathe */
601 	if (strlen(filename) > PATH_MAX - 16) {
602 		errno = ENAMETOOLONG;
603 		return -1;
604 	}
605 
606 	if (numbered) {
607 		/* If some crazy person needs more than 65536 backup files,
608 		   they probably have more serious issues to tend to. */
609 		int n = 1, ret;
610 		do {
611 			sprintf(buf, "%s.%d~", filename, n++);
612 			ret = rename_file(filename, buf, 0);
613 		} while (ret != 0 && errno == EEXIST && n < 65536);
614 		return ret;
615 	} else {
616 		strcpy(buf, filename);
617 		strcat(buf, "~");
618 		return rename_file(filename, buf, 1);
619 	}
620 }
621 
622 long file_size(const char *filename)
623 {
624 	struct stat buf;
625 
626 	if (stat(filename, &buf) < 0) {
627 		return EOF;
628 	}
629 	if (S_ISDIR(buf.st_mode)) {
630 		errno = EISDIR;
631 		return EOF;
632 	}
633 	return buf.st_size;
634 }
635 
636 /* --------------------------------------------------------------------- */
637 /* FILESYSTEM FUNCTIONS */
638 
639 int is_directory(const char *filename)
640 {
641 	struct stat buf;
642 
643 	if (stat(filename, &buf) == -1) {
644 		/* Well, at least we tried. */
645 		return 0;
646 	}
647 
648 	return S_ISDIR(buf.st_mode);
649 }
650 
651 char *get_current_directory(void)
652 {
653 	char buf[PATH_MAX + 1];
654 
655 	/* hmm. fall back to the current dir */
656 	if (getcwd(buf, PATH_MAX))
657 		return str_dup(buf);
658 	return str_dup(".");
659 }
660 
661 /* this function is horrible */
662 char *get_home_directory(void)
663 {
664 	char buf[PATH_MAX + 1];
665 
666 #if defined(__amigaos4__)
667 	return str_dup("PROGDIR:");
668 #elif defined(WIN32)
669 	if (SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, 0, buf) == ERROR_SUCCESS)
670 		return strdup(buf);
671 #else
672 	char *ptr = getenv("HOME");
673 	if (ptr)
674 		return str_dup(ptr);
675 #endif
676 
677 	/* hmm. fall back to the current dir */
678 	if (getcwd(buf, PATH_MAX))
679 		return str_dup(buf);
680 
681 	/* still don't have a directory? sheesh. */
682 	return str_dup(FALLBACK_DIR);
683 }
684 
685 char *get_dot_directory(void)
686 {
687 #ifdef WIN32
688 	char buf[PATH_MAX + 1];
689 	if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, buf) == ERROR_SUCCESS)
690 		return strdup(buf);
691 	// else fall back to home (but if this ever happens, things are really screwed...)
692 #endif
693 	return get_home_directory();
694 }
695 
696 char *str_concat(const char *s, ...)
697 {
698 	va_list ap;
699 	char *out = NULL;
700 	int len = 0;
701 
702 	va_start(ap,s);
703 	while (s) {
704 		out = mem_realloc(out, (len += strlen(s)+1));
705 		strcat(out, s);
706 		s = va_arg(ap, const char *);
707 	}
708 	va_end(ap);
709 	return out;
710 
711 }
712 
713 void unset_env_var(const char *key)
714 {
715 #ifdef HAVE_UNSETENV
716 	unsetenv(key);
717 #else
718 	/* assume POSIX-style semantics */
719 	putenv(key);
720 #endif
721 }
722 
723 void put_env_var(const char *key, const char *value)
724 {
725 	char *x;
726 	x = mem_alloc(strlen(key) + strlen(value)+2);
727 	sprintf(x, "%s=%s", key,value);
728 	if (putenv(x) == -1) {
729 		perror("putenv");
730 		exit(255); /* memory exception */
731 	}
732 }
733 
734 /* fast integer sqrt */
735 unsigned int i_sqrt(unsigned int r)
736 {
737 	unsigned int t, b, c=0;
738 	for (b = 0x10000000; b != 0; b >>= 2) {
739 		t = c + b;
740 		c >>= 1;
741 		if (t <= r) {
742 			r -= t;
743 			c += b;
744 		}
745 	}
746 	return(c);
747 }
748 
749 int run_hook(const char *dir, const char *name, const char *maybe_arg)
750 {
751 #ifdef WIN32
752 	char buf[PATH_MAX];
753 	const char *ptr;
754 	char buf2[PATH_MAX];
755 	struct stat sb;
756 	int r;
757 
758 	if (!GetCurrentDirectory(PATH_MAX-1,buf)) return 0;
759 	snprintf(buf2, PATH_MAX-2, "%s.bat", name);
760 	if (chdir(dir) == -1) return 0;
761 	if (stat(buf2, &sb) == -1) {
762 		r = 0;
763 	} else {
764 		ptr = getenv("COMSPEC") ?: "command.com";
765 		r = _spawnlp(_P_WAIT, ptr, ptr, "/c", buf2, maybe_arg, 0);
766 	}
767 	SetCurrentDirectory(buf);
768 	chdir(buf);
769 	if (r == 0) return 1;
770 	return 0;
771 #elif defined(GEKKO)
772 	// help how do I operating system
773 	(void) dir;
774 	(void) name;
775 	(void) maybe_arg;
776 	return 0;
777 #else
778 	char *tmp;
779 	int st;
780 
781 	switch (fork()) {
782 	case -1: return 0;
783 	case 0:
784 		if (chdir(dir) == -1) _exit(255);
785 		tmp = malloc(strlen(name)+4);
786 		if (!tmp) _exit(255);
787 		sprintf(tmp, "./%s", name);
788 		execl(tmp, tmp, maybe_arg, NULL);
789 		free(tmp);
790 		_exit(255);
791 	};
792 	while (wait(&st) == -1) {
793 	}
794 	if (WIFEXITED(st) && WEXITSTATUS(st) == 0) return 1;
795 	return 0;
796 #endif
797 }
798 
799 /* --------------------------------------------------------------------------------------------------------- */
800 
801 static int _rename_nodestroy(const char *old, const char *new)
802 {
803 /* XXX does __amigaos4__ have a special need for this? */
804 #ifdef WIN32
805 	/* is this code not finished? it never returns success */
806 	UINT em = SetErrorMode(0);
807 	if (!MoveFile(old, new)) {
808 		switch (GetLastError()) {
809 		case ERROR_ALREADY_EXISTS:
810 		case ERROR_FILE_EXISTS:
811 			SetErrorMode(em);
812 			errno = EEXIST;
813 			return -1;
814 		};
815 		SetErrorMode(em);
816 		return -1;
817 	}
818 	SetErrorMode(em);
819 	return 0;
820 #else
821 	if (link(old, new) == -1) {
822 		return -1;
823 	}
824 	if (unlink(old) == -1) {
825 		/* This can occur when people are using a system with
826 		broken link() semantics, or if the user can create files
827 		that he cannot remove. these systems are decidedly not POSIX.1
828 		but they may try to compile schism, and we won't know they
829 		are broken unless we warn them.
830 		*/
831 		fprintf(stderr, "link() succeeded, but unlink() failed. something is very wrong\n");
832 	}
833 	return 0;
834 #endif
835 }
836 
837 /* 0 = success, !0 = failed (check errno) */
838 int rename_file(const char *old, const char *new, int overwrite)
839 {
840 	if (!overwrite)
841 		return _rename_nodestroy(old, new);
842 
843 #ifdef WIN32
844 	UINT em;
845 	em = SetErrorMode(0);
846 	if (MoveFile(old, new)) {
847 		win32_filecreated_callback(new);
848 		return 0;
849 	}
850 	switch (GetLastError()) {
851 	case ERROR_ALREADY_EXISTS:
852 	case ERROR_FILE_EXISTS:
853 		break;
854 	default:
855 		/* eh... */
856 		SetErrorMode(em);
857 		return -1;
858 	};
859 
860 	if (MoveFileEx(old, new, MOVEFILE_REPLACE_EXISTING)) {
861 		/* yay */
862 		SetErrorMode(em);
863 		return 0;
864 	}
865 	/* this sometimes work with win95 and novell shares */
866 	chmod(new, 0777);
867 	chmod(old, 0777);
868 	/* more junk */
869 	SetFileAttributesA(new, FILE_ATTRIBUTE_NORMAL);
870 	SetFileAttributesA(new, FILE_ATTRIBUTE_TEMPORARY);
871 
872 	if (MoveFile(old, new)) {
873 		/* err.. yay! */
874 		win32_filecreated_callback(new);
875 		SetErrorMode(em);
876 		return 0;
877 	}
878 	/* okay, let's try again */
879 	if (!DeleteFileA(new)) {
880 		/* no chance! */
881 		SetErrorMode(em);
882 		return -1;
883 	}
884 	if (MoveFile(old, new)) {
885 		/* .... */
886 		win32_filecreated_callback(new);
887 		SetErrorMode(em);
888 		return 0;
889 	}
890 	/* alright, thems the breaks. win95 eats your files,
891 	and not a damn thing I can do about it.
892 	*/
893 	SetErrorMode(em);
894 	return -1;
895 #else
896 	int r = rename(old, new);
897 	if (r != 0 && errno == EEXIST) {
898 		/* Broken rename()? Try smashing the old file first,
899 		and hope *that* doesn't also fail ;) */
900 		if (unlink(old) != 0 || rename(old, new) == -1)
901 			return -1;
902 	}
903 	return r;
904 #endif
905 }
906 
907