1 /* 2 * Copyright (c) 2012 - 2014 Tony Finch <dot@dotat.at> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include "unifdef.h" 27 28 /* 29 * The Windows implementation of rename() fails if the new filename 30 * already exists. Atomic replacement is not really needed, so just 31 * remove anything that might be in the way before renaming. 32 */ 33 int 34 replace(const char *oldname, const char *newname) 35 { 36 if (remove(newname) < 0 && errno != ENOENT) 37 warn("can't remove \"%s\"", newname); 38 return (rename(oldname, newname)); 39 } 40 41 FILE * 42 mktempmode(char *tmp, int mode) 43 { 44 mode = mode; 45 return (fopen(_mktemp(tmp), "wb")); 46 } 47 48 FILE * 49 fbinmode(FILE *fp) 50 { 51 _setmode(_fileno(fp), _O_BINARY); 52 return (fp); 53 } 54 55 /* 56 * This is more long-winded than seems necessary because MinGW 57 * doesn't have a proper implementation of _vsnprintf_s(). 58 * 59 * This link has some useful info about snprintf() on Windows: 60 * http://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010 61 */ 62 int c99_snprintf(char *buf, size_t buflen, const char *format, ...) 63 { 64 va_list ap; 65 int outlen, cpylen, tmplen; 66 char *tmp; 67 68 va_start(ap, format); 69 outlen = _vscprintf(format, ap); 70 va_end(ap); 71 if (buflen == 0 || outlen < 0) 72 return outlen; 73 if (buflen > outlen) 74 cpylen = outlen; 75 else 76 cpylen = buflen - 1; 77 /* Paranoia about off-by-one errors in _snprintf() */ 78 tmplen = outlen + 2; 79 80 tmp = (char *)malloc(tmplen); 81 if (tmp == NULL) 82 err(2, "malloc"); 83 va_start(ap, format); 84 _vsnprintf(tmp, tmplen, format, ap); 85 va_end(ap); 86 memcpy(buf, tmp, cpylen); 87 buf[cpylen] = '\0'; 88 free(tmp); 89 90 return outlen; 91 } 92