1caf54c4fSMartin Matuska /*- 2*6c95142eSMartin Matuska * Copyright (c) 2009,2010 Michihiro NAKAJIMA 3caf54c4fSMartin Matuska * Copyright (c) 2003-2007 Tim Kientzle 4caf54c4fSMartin Matuska * All rights reserved. 5caf54c4fSMartin Matuska * 6caf54c4fSMartin Matuska * Redistribution and use in source and binary forms, with or without 7caf54c4fSMartin Matuska * modification, are permitted provided that the following conditions 8caf54c4fSMartin Matuska * are met: 9caf54c4fSMartin Matuska * 1. Redistributions of source code must retain the above copyright 10caf54c4fSMartin Matuska * notice, this list of conditions and the following disclaimer. 11caf54c4fSMartin Matuska * 2. Redistributions in binary form must reproduce the above copyright 12caf54c4fSMartin Matuska * notice, this list of conditions and the following disclaimer in the 13caf54c4fSMartin Matuska * documentation and/or other materials provided with the distribution. 14caf54c4fSMartin Matuska * 15caf54c4fSMartin Matuska * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16caf54c4fSMartin Matuska * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17caf54c4fSMartin Matuska * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18caf54c4fSMartin Matuska * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19caf54c4fSMartin Matuska * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20caf54c4fSMartin Matuska * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21caf54c4fSMartin Matuska * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22caf54c4fSMartin Matuska * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23caf54c4fSMartin Matuska * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24caf54c4fSMartin Matuska * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25caf54c4fSMartin Matuska */ 26caf54c4fSMartin Matuska 27caf54c4fSMartin Matuska #include "archive_platform.h" 286c22d9efSMartin Matuska __FBSDID("$FreeBSD$"); 29caf54c4fSMartin Matuska 30caf54c4fSMartin Matuska #ifdef HAVE_SYS_TYPES_H 31caf54c4fSMartin Matuska #include <sys/types.h> 32caf54c4fSMartin Matuska #endif 33*6c95142eSMartin Matuska #ifdef HAVE_ERRNO_H 34*6c95142eSMartin Matuska #include <errno.h> 35*6c95142eSMartin Matuska #endif 36*6c95142eSMartin Matuska #ifdef HAVE_FCNTL_H 37*6c95142eSMartin Matuska #include <fcntl.h> 38*6c95142eSMartin Matuska #endif 39caf54c4fSMartin Matuska #ifdef HAVE_STDLIB_H 40caf54c4fSMartin Matuska #include <stdlib.h> 41caf54c4fSMartin Matuska #endif 42caf54c4fSMartin Matuska #ifdef HAVE_STRING_H 43caf54c4fSMartin Matuska #include <string.h> 44caf54c4fSMartin Matuska #endif 45*6c95142eSMartin Matuska #if defined(HAVE_WINCRYPT_H) && !defined(__CYGWIN__) 46*6c95142eSMartin Matuska #include <wincrypt.h> 47*6c95142eSMartin Matuska #endif 48caf54c4fSMartin Matuska 49caf54c4fSMartin Matuska #include "archive.h" 50caf54c4fSMartin Matuska #include "archive_private.h" 51caf54c4fSMartin Matuska #include "archive_string.h" 52caf54c4fSMartin Matuska 53*6c95142eSMartin Matuska /* Generic initialization of 'struct archive' objects. */ 54caf54c4fSMartin Matuska int 55*6c95142eSMartin Matuska __archive_clean(struct archive *a) 56caf54c4fSMartin Matuska { 57*6c95142eSMartin Matuska archive_string_conversion_free(a); 58*6c95142eSMartin Matuska return (ARCHIVE_OK); 59caf54c4fSMartin Matuska } 60caf54c4fSMartin Matuska 61caf54c4fSMartin Matuska int 62caf54c4fSMartin Matuska archive_version_number(void) 63caf54c4fSMartin Matuska { 64caf54c4fSMartin Matuska return (ARCHIVE_VERSION_NUMBER); 65caf54c4fSMartin Matuska } 66caf54c4fSMartin Matuska 67caf54c4fSMartin Matuska const char * 68caf54c4fSMartin Matuska archive_version_string(void) 69caf54c4fSMartin Matuska { 70caf54c4fSMartin Matuska return (ARCHIVE_VERSION_STRING); 71caf54c4fSMartin Matuska } 72caf54c4fSMartin Matuska 73caf54c4fSMartin Matuska int 74caf54c4fSMartin Matuska archive_errno(struct archive *a) 75caf54c4fSMartin Matuska { 76caf54c4fSMartin Matuska return (a->archive_error_number); 77caf54c4fSMartin Matuska } 78caf54c4fSMartin Matuska 79caf54c4fSMartin Matuska const char * 80caf54c4fSMartin Matuska archive_error_string(struct archive *a) 81caf54c4fSMartin Matuska { 82caf54c4fSMartin Matuska 83caf54c4fSMartin Matuska if (a->error != NULL && *a->error != '\0') 84caf54c4fSMartin Matuska return (a->error); 85caf54c4fSMartin Matuska else 86*6c95142eSMartin Matuska return (NULL); 87caf54c4fSMartin Matuska } 88caf54c4fSMartin Matuska 89caf54c4fSMartin Matuska int 90caf54c4fSMartin Matuska archive_file_count(struct archive *a) 91caf54c4fSMartin Matuska { 92caf54c4fSMartin Matuska return (a->file_count); 93caf54c4fSMartin Matuska } 94caf54c4fSMartin Matuska 95caf54c4fSMartin Matuska int 96caf54c4fSMartin Matuska archive_format(struct archive *a) 97caf54c4fSMartin Matuska { 98caf54c4fSMartin Matuska return (a->archive_format); 99caf54c4fSMartin Matuska } 100caf54c4fSMartin Matuska 101caf54c4fSMartin Matuska const char * 102caf54c4fSMartin Matuska archive_format_name(struct archive *a) 103caf54c4fSMartin Matuska { 104caf54c4fSMartin Matuska return (a->archive_format_name); 105caf54c4fSMartin Matuska } 106caf54c4fSMartin Matuska 107caf54c4fSMartin Matuska 108caf54c4fSMartin Matuska int 109caf54c4fSMartin Matuska archive_compression(struct archive *a) 110caf54c4fSMartin Matuska { 111*6c95142eSMartin Matuska return archive_filter_code(a, 0); 112caf54c4fSMartin Matuska } 113caf54c4fSMartin Matuska 114caf54c4fSMartin Matuska const char * 115caf54c4fSMartin Matuska archive_compression_name(struct archive *a) 116caf54c4fSMartin Matuska { 117*6c95142eSMartin Matuska return archive_filter_name(a, 0); 118caf54c4fSMartin Matuska } 119caf54c4fSMartin Matuska 120caf54c4fSMartin Matuska 121caf54c4fSMartin Matuska /* 122caf54c4fSMartin Matuska * Return a count of the number of compressed bytes processed. 123caf54c4fSMartin Matuska */ 124caf54c4fSMartin Matuska int64_t 125caf54c4fSMartin Matuska archive_position_compressed(struct archive *a) 126caf54c4fSMartin Matuska { 127*6c95142eSMartin Matuska return archive_filter_bytes(a, -1); 128caf54c4fSMartin Matuska } 129caf54c4fSMartin Matuska 130caf54c4fSMartin Matuska /* 131caf54c4fSMartin Matuska * Return a count of the number of uncompressed bytes processed. 132caf54c4fSMartin Matuska */ 133caf54c4fSMartin Matuska int64_t 134caf54c4fSMartin Matuska archive_position_uncompressed(struct archive *a) 135caf54c4fSMartin Matuska { 136*6c95142eSMartin Matuska return archive_filter_bytes(a, 0); 137caf54c4fSMartin Matuska } 138caf54c4fSMartin Matuska 139caf54c4fSMartin Matuska void 140caf54c4fSMartin Matuska archive_clear_error(struct archive *a) 141caf54c4fSMartin Matuska { 142caf54c4fSMartin Matuska archive_string_empty(&a->error_string); 143caf54c4fSMartin Matuska a->error = NULL; 144caf54c4fSMartin Matuska a->archive_error_number = 0; 145caf54c4fSMartin Matuska } 146caf54c4fSMartin Matuska 147caf54c4fSMartin Matuska void 148caf54c4fSMartin Matuska archive_set_error(struct archive *a, int error_number, const char *fmt, ...) 149caf54c4fSMartin Matuska { 150caf54c4fSMartin Matuska va_list ap; 151caf54c4fSMartin Matuska 152caf54c4fSMartin Matuska a->archive_error_number = error_number; 153caf54c4fSMartin Matuska if (fmt == NULL) { 154caf54c4fSMartin Matuska a->error = NULL; 155caf54c4fSMartin Matuska return; 156caf54c4fSMartin Matuska } 157caf54c4fSMartin Matuska 158*6c95142eSMartin Matuska archive_string_empty(&(a->error_string)); 159caf54c4fSMartin Matuska va_start(ap, fmt); 160caf54c4fSMartin Matuska archive_string_vsprintf(&(a->error_string), fmt, ap); 161caf54c4fSMartin Matuska va_end(ap); 162caf54c4fSMartin Matuska a->error = a->error_string.s; 163caf54c4fSMartin Matuska } 164caf54c4fSMartin Matuska 165caf54c4fSMartin Matuska void 166caf54c4fSMartin Matuska archive_copy_error(struct archive *dest, struct archive *src) 167caf54c4fSMartin Matuska { 168caf54c4fSMartin Matuska dest->archive_error_number = src->archive_error_number; 169caf54c4fSMartin Matuska 170caf54c4fSMartin Matuska archive_string_copy(&dest->error_string, &src->error_string); 171caf54c4fSMartin Matuska dest->error = dest->error_string.s; 172caf54c4fSMartin Matuska } 173caf54c4fSMartin Matuska 174caf54c4fSMartin Matuska void 175caf54c4fSMartin Matuska __archive_errx(int retvalue, const char *msg) 176caf54c4fSMartin Matuska { 177caf54c4fSMartin Matuska static const char *msg1 = "Fatal Internal Error in libarchive: "; 178caf54c4fSMartin Matuska size_t s; 179caf54c4fSMartin Matuska 180caf54c4fSMartin Matuska s = write(2, msg1, strlen(msg1)); 181caf54c4fSMartin Matuska (void)s; /* UNUSED */ 182caf54c4fSMartin Matuska s = write(2, msg, strlen(msg)); 183caf54c4fSMartin Matuska (void)s; /* UNUSED */ 184caf54c4fSMartin Matuska s = write(2, "\n", 1); 185caf54c4fSMartin Matuska (void)s; /* UNUSED */ 186caf54c4fSMartin Matuska exit(retvalue); 187caf54c4fSMartin Matuska } 188caf54c4fSMartin Matuska 189caf54c4fSMartin Matuska /* 190*6c95142eSMartin Matuska * Create a temporary file 191*6c95142eSMartin Matuska */ 192*6c95142eSMartin Matuska #if defined(_WIN32) && !defined(__CYGWIN__) 193*6c95142eSMartin Matuska 194*6c95142eSMartin Matuska /* 195*6c95142eSMartin Matuska * Do not use Windows tmpfile() function. 196*6c95142eSMartin Matuska * It will make a temporary file under the root directory 197*6c95142eSMartin Matuska * and it'll cause permission error if a user who is 198*6c95142eSMartin Matuska * non-Administrator creates temporary files. 199*6c95142eSMartin Matuska * Also Windows version of mktemp family including _mktemp_s 200*6c95142eSMartin Matuska * are not secure. 201caf54c4fSMartin Matuska */ 202caf54c4fSMartin Matuska int 203*6c95142eSMartin Matuska __archive_mktemp(const char *tmpdir) 204caf54c4fSMartin Matuska { 205*6c95142eSMartin Matuska static const wchar_t num[] = { 206*6c95142eSMartin Matuska L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', 207*6c95142eSMartin Matuska L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F', 208*6c95142eSMartin Matuska L'G', L'H', L'I', L'J', L'K', L'L', L'M', L'N', 209*6c95142eSMartin Matuska L'O', L'P', L'Q', L'R', L'S', L'T', L'U', L'V', 210*6c95142eSMartin Matuska L'W', L'X', L'Y', L'Z', L'a', L'b', L'c', L'd', 211*6c95142eSMartin Matuska L'e', L'f', L'g', L'h', L'i', L'j', L'k', L'l', 212*6c95142eSMartin Matuska L'm', L'n', L'o', L'p', L'q', L'r', L's', L't', 213*6c95142eSMartin Matuska L'u', L'v', L'w', L'x', L'y', L'z' 214*6c95142eSMartin Matuska }; 215*6c95142eSMartin Matuska HCRYPTPROV hProv; 216*6c95142eSMartin Matuska struct archive_wstring temp_name; 217*6c95142eSMartin Matuska wchar_t *ws; 218*6c95142eSMartin Matuska DWORD attr; 219*6c95142eSMartin Matuska wchar_t *xp, *ep; 220*6c95142eSMartin Matuska int fd; 221caf54c4fSMartin Matuska 222*6c95142eSMartin Matuska hProv = (HCRYPTPROV)NULL; 223*6c95142eSMartin Matuska fd = -1; 224*6c95142eSMartin Matuska ws = NULL; 225*6c95142eSMartin Matuska archive_string_init(&temp_name); 226*6c95142eSMartin Matuska 227*6c95142eSMartin Matuska /* Get a temporary directory. */ 228*6c95142eSMartin Matuska if (tmpdir == NULL) { 229*6c95142eSMartin Matuska size_t l; 230*6c95142eSMartin Matuska wchar_t *tmp; 231*6c95142eSMartin Matuska 232*6c95142eSMartin Matuska l = GetTempPathW(0, NULL); 233*6c95142eSMartin Matuska if (l == 0) { 234*6c95142eSMartin Matuska la_dosmaperr(GetLastError()); 235*6c95142eSMartin Matuska goto exit_tmpfile; 236*6c95142eSMartin Matuska } 237*6c95142eSMartin Matuska tmp = malloc(l*sizeof(wchar_t)); 238*6c95142eSMartin Matuska if (tmp == NULL) { 239*6c95142eSMartin Matuska errno = ENOMEM; 240*6c95142eSMartin Matuska goto exit_tmpfile; 241*6c95142eSMartin Matuska } 242*6c95142eSMartin Matuska GetTempPathW(l, tmp); 243*6c95142eSMartin Matuska archive_wstrcpy(&temp_name, tmp); 244*6c95142eSMartin Matuska free(tmp); 245caf54c4fSMartin Matuska } else { 246*6c95142eSMartin Matuska archive_wstring_append_from_mbs(&temp_name, tmpdir, 247*6c95142eSMartin Matuska strlen(tmpdir)); 248*6c95142eSMartin Matuska if (temp_name.s[temp_name.length-1] != L'/') 249*6c95142eSMartin Matuska archive_wstrappend_wchar(&temp_name, L'/'); 250caf54c4fSMartin Matuska } 251*6c95142eSMartin Matuska 252*6c95142eSMartin Matuska /* Check if temp_name is a directory. */ 253*6c95142eSMartin Matuska attr = GetFileAttributesW(temp_name.s); 254*6c95142eSMartin Matuska if (attr == (DWORD)-1) { 255*6c95142eSMartin Matuska if (GetLastError() != ERROR_FILE_NOT_FOUND) { 256*6c95142eSMartin Matuska la_dosmaperr(GetLastError()); 257*6c95142eSMartin Matuska goto exit_tmpfile; 258*6c95142eSMartin Matuska } 259*6c95142eSMartin Matuska ws = __la_win_permissive_name_w(temp_name.s); 260*6c95142eSMartin Matuska if (ws == NULL) { 261*6c95142eSMartin Matuska errno = EINVAL; 262*6c95142eSMartin Matuska goto exit_tmpfile; 263*6c95142eSMartin Matuska } 264*6c95142eSMartin Matuska attr = GetFileAttributesW(ws); 265*6c95142eSMartin Matuska if (attr == (DWORD)-1) { 266*6c95142eSMartin Matuska la_dosmaperr(GetLastError()); 267*6c95142eSMartin Matuska goto exit_tmpfile; 268*6c95142eSMartin Matuska } 269*6c95142eSMartin Matuska } 270*6c95142eSMartin Matuska if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { 271*6c95142eSMartin Matuska errno = ENOTDIR; 272*6c95142eSMartin Matuska goto exit_tmpfile; 273*6c95142eSMartin Matuska } 274*6c95142eSMartin Matuska 275*6c95142eSMartin Matuska /* 276*6c95142eSMartin Matuska * Create a temporary file. 277*6c95142eSMartin Matuska */ 278*6c95142eSMartin Matuska archive_wstrcat(&temp_name, L"libarchive_"); 279*6c95142eSMartin Matuska xp = temp_name.s + archive_strlen(&temp_name); 280*6c95142eSMartin Matuska archive_wstrcat(&temp_name, L"XXXXXXXXXX"); 281*6c95142eSMartin Matuska ep = temp_name.s + archive_strlen(&temp_name); 282*6c95142eSMartin Matuska 283*6c95142eSMartin Matuska if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, 284*6c95142eSMartin Matuska CRYPT_VERIFYCONTEXT)) { 285*6c95142eSMartin Matuska la_dosmaperr(GetLastError()); 286*6c95142eSMartin Matuska goto exit_tmpfile; 287*6c95142eSMartin Matuska } 288*6c95142eSMartin Matuska 289*6c95142eSMartin Matuska for (;;) { 290*6c95142eSMartin Matuska wchar_t *p; 291*6c95142eSMartin Matuska HANDLE h; 292*6c95142eSMartin Matuska 293*6c95142eSMartin Matuska /* Generate a random file name through CryptGenRandom(). */ 294*6c95142eSMartin Matuska p = xp; 295*6c95142eSMartin Matuska if (!CryptGenRandom(hProv, (ep - p)*sizeof(wchar_t), (BYTE*)p)) { 296*6c95142eSMartin Matuska la_dosmaperr(GetLastError()); 297*6c95142eSMartin Matuska goto exit_tmpfile; 298*6c95142eSMartin Matuska } 299*6c95142eSMartin Matuska for (; p < ep; p++) 300*6c95142eSMartin Matuska *p = num[((DWORD)*p) % (sizeof(num)/sizeof(num[0]))]; 301*6c95142eSMartin Matuska 302*6c95142eSMartin Matuska free(ws); 303*6c95142eSMartin Matuska ws = __la_win_permissive_name_w(temp_name.s); 304*6c95142eSMartin Matuska if (ws == NULL) { 305*6c95142eSMartin Matuska errno = EINVAL; 306*6c95142eSMartin Matuska goto exit_tmpfile; 307*6c95142eSMartin Matuska } 308*6c95142eSMartin Matuska /* Specifies FILE_FLAG_DELETE_ON_CLOSE flag is to 309*6c95142eSMartin Matuska * delete this temporary file immediately when this 310*6c95142eSMartin Matuska * file closed. */ 311*6c95142eSMartin Matuska h = CreateFileW(ws, 312*6c95142eSMartin Matuska GENERIC_READ | GENERIC_WRITE | DELETE, 313*6c95142eSMartin Matuska 0,/* Not share */ 314*6c95142eSMartin Matuska NULL, 315*6c95142eSMartin Matuska CREATE_NEW,/* Create a new file only */ 316*6c95142eSMartin Matuska FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, 317*6c95142eSMartin Matuska NULL); 318*6c95142eSMartin Matuska if (h == INVALID_HANDLE_VALUE) { 319*6c95142eSMartin Matuska /* The same file already exists. retry with 320*6c95142eSMartin Matuska * a new filename. */ 321*6c95142eSMartin Matuska if (GetLastError() == ERROR_FILE_EXISTS) 322*6c95142eSMartin Matuska continue; 323*6c95142eSMartin Matuska /* Otherwise, fail creation temporary file. */ 324*6c95142eSMartin Matuska la_dosmaperr(GetLastError()); 325*6c95142eSMartin Matuska goto exit_tmpfile; 326*6c95142eSMartin Matuska } 327*6c95142eSMartin Matuska fd = _open_osfhandle((intptr_t)h, _O_BINARY | _O_RDWR); 328*6c95142eSMartin Matuska if (fd == -1) { 329*6c95142eSMartin Matuska CloseHandle(h); 330*6c95142eSMartin Matuska goto exit_tmpfile; 331*6c95142eSMartin Matuska } else 332*6c95142eSMartin Matuska break;/* success! */ 333*6c95142eSMartin Matuska } 334*6c95142eSMartin Matuska exit_tmpfile: 335*6c95142eSMartin Matuska if (hProv != (HCRYPTPROV)NULL) 336*6c95142eSMartin Matuska CryptReleaseContext(hProv, 0); 337*6c95142eSMartin Matuska free(ws); 338*6c95142eSMartin Matuska archive_wstring_free(&temp_name); 339*6c95142eSMartin Matuska return (fd); 340*6c95142eSMartin Matuska } 341*6c95142eSMartin Matuska 342*6c95142eSMartin Matuska #else 343*6c95142eSMartin Matuska 344*6c95142eSMartin Matuska static int 345*6c95142eSMartin Matuska get_tempdir(struct archive_string *temppath) 346*6c95142eSMartin Matuska { 347*6c95142eSMartin Matuska const char *tmp; 348*6c95142eSMartin Matuska 349*6c95142eSMartin Matuska tmp = getenv("TMPDIR"); 350*6c95142eSMartin Matuska if (tmp == NULL) 351*6c95142eSMartin Matuska #ifdef _PATH_TMP 352*6c95142eSMartin Matuska tmp = _PATH_TMP; 353*6c95142eSMartin Matuska #else 354*6c95142eSMartin Matuska tmp = "/tmp"; 355*6c95142eSMartin Matuska #endif 356*6c95142eSMartin Matuska archive_strcpy(temppath, tmp); 357*6c95142eSMartin Matuska if (temppath->s[temppath->length-1] != '/') 358*6c95142eSMartin Matuska archive_strappend_char(temppath, '/'); 359*6c95142eSMartin Matuska return (ARCHIVE_OK); 360*6c95142eSMartin Matuska } 361*6c95142eSMartin Matuska 362*6c95142eSMartin Matuska #if defined(HAVE_MKSTEMP) 363*6c95142eSMartin Matuska 364*6c95142eSMartin Matuska /* 365*6c95142eSMartin Matuska * We can use mkstemp(). 366*6c95142eSMartin Matuska */ 367*6c95142eSMartin Matuska 368*6c95142eSMartin Matuska int 369*6c95142eSMartin Matuska __archive_mktemp(const char *tmpdir) 370*6c95142eSMartin Matuska { 371*6c95142eSMartin Matuska struct archive_string temp_name; 372*6c95142eSMartin Matuska int fd = -1; 373*6c95142eSMartin Matuska 374*6c95142eSMartin Matuska archive_string_init(&temp_name); 375*6c95142eSMartin Matuska if (tmpdir == NULL) { 376*6c95142eSMartin Matuska if (get_tempdir(&temp_name) != ARCHIVE_OK) 377*6c95142eSMartin Matuska goto exit_tmpfile; 378caf54c4fSMartin Matuska } else { 379*6c95142eSMartin Matuska archive_strcpy(&temp_name, tmpdir); 380*6c95142eSMartin Matuska if (temp_name.s[temp_name.length-1] != '/') 381*6c95142eSMartin Matuska archive_strappend_char(&temp_name, '/'); 382caf54c4fSMartin Matuska } 383*6c95142eSMartin Matuska archive_strcat(&temp_name, "libarchive_XXXXXX"); 384*6c95142eSMartin Matuska fd = mkstemp(temp_name.s); 385*6c95142eSMartin Matuska if (fd < 0) 386*6c95142eSMartin Matuska goto exit_tmpfile; 387*6c95142eSMartin Matuska unlink(temp_name.s); 388*6c95142eSMartin Matuska exit_tmpfile: 389*6c95142eSMartin Matuska archive_string_free(&temp_name); 390*6c95142eSMartin Matuska return (fd); 391caf54c4fSMartin Matuska } 392caf54c4fSMartin Matuska 393*6c95142eSMartin Matuska #else 394*6c95142eSMartin Matuska 395*6c95142eSMartin Matuska /* 396*6c95142eSMartin Matuska * We use a private routine. 397*6c95142eSMartin Matuska */ 398*6c95142eSMartin Matuska 399*6c95142eSMartin Matuska int 400*6c95142eSMartin Matuska __archive_mktemp(const char *tmpdir) 401*6c95142eSMartin Matuska { 402*6c95142eSMartin Matuska static const char num[] = { 403*6c95142eSMartin Matuska '0', '1', '2', '3', '4', '5', '6', '7', 404*6c95142eSMartin Matuska '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 405*6c95142eSMartin Matuska 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 406*6c95142eSMartin Matuska 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 407*6c95142eSMartin Matuska 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 408*6c95142eSMartin Matuska 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 409*6c95142eSMartin Matuska 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 410*6c95142eSMartin Matuska 'u', 'v', 'w', 'x', 'y', 'z' 411*6c95142eSMartin Matuska }; 412*6c95142eSMartin Matuska struct archive_string temp_name; 413*6c95142eSMartin Matuska struct stat st; 414*6c95142eSMartin Matuska int fd; 415*6c95142eSMartin Matuska char *tp, *ep; 416*6c95142eSMartin Matuska unsigned seed; 417*6c95142eSMartin Matuska 418*6c95142eSMartin Matuska fd = -1; 419*6c95142eSMartin Matuska archive_string_init(&temp_name); 420*6c95142eSMartin Matuska if (tmpdir == NULL) { 421*6c95142eSMartin Matuska if (get_tempdir(&temp_name) != ARCHIVE_OK) 422*6c95142eSMartin Matuska goto exit_tmpfile; 423*6c95142eSMartin Matuska } else 424*6c95142eSMartin Matuska archive_strcpy(&temp_name, tmpdir); 425*6c95142eSMartin Matuska if (temp_name.s[temp_name.length-1] == '/') { 426*6c95142eSMartin Matuska temp_name.s[temp_name.length-1] = '\0'; 427*6c95142eSMartin Matuska temp_name.length --; 428caf54c4fSMartin Matuska } 429*6c95142eSMartin Matuska if (stat(temp_name.s, &st) < 0) 430*6c95142eSMartin Matuska goto exit_tmpfile; 431*6c95142eSMartin Matuska if (!S_ISDIR(st.st_mode)) { 432*6c95142eSMartin Matuska errno = ENOTDIR; 433*6c95142eSMartin Matuska goto exit_tmpfile; 434*6c95142eSMartin Matuska } 435*6c95142eSMartin Matuska archive_strcat(&temp_name, "/libarchive_"); 436*6c95142eSMartin Matuska tp = temp_name.s + archive_strlen(&temp_name); 437*6c95142eSMartin Matuska archive_strcat(&temp_name, "XXXXXXXXXX"); 438*6c95142eSMartin Matuska ep = temp_name.s + archive_strlen(&temp_name); 439*6c95142eSMartin Matuska 440*6c95142eSMartin Matuska fd = open("/dev/random", O_RDONLY); 441*6c95142eSMartin Matuska if (fd < 0) 442*6c95142eSMartin Matuska seed = time(NULL); 443*6c95142eSMartin Matuska else { 444*6c95142eSMartin Matuska if (read(fd, &seed, sizeof(seed)) < 0) 445*6c95142eSMartin Matuska seed = time(NULL); 446*6c95142eSMartin Matuska close(fd); 447*6c95142eSMartin Matuska } 448*6c95142eSMartin Matuska do { 449*6c95142eSMartin Matuska char *p; 450*6c95142eSMartin Matuska 451*6c95142eSMartin Matuska p = tp; 452*6c95142eSMartin Matuska while (p < ep) 453*6c95142eSMartin Matuska *p++ = num[((unsigned)rand_r(&seed)) % sizeof(num)]; 454*6c95142eSMartin Matuska fd = open(temp_name.s, O_CREAT | O_EXCL | O_RDWR, 0600); 455*6c95142eSMartin Matuska } while (fd < 0 && errno == EEXIST); 456*6c95142eSMartin Matuska if (fd < 0) 457*6c95142eSMartin Matuska goto exit_tmpfile; 458*6c95142eSMartin Matuska unlink(temp_name.s); 459*6c95142eSMartin Matuska exit_tmpfile: 460*6c95142eSMartin Matuska archive_string_free(&temp_name); 461*6c95142eSMartin Matuska return (fd); 462caf54c4fSMartin Matuska } 463caf54c4fSMartin Matuska 464*6c95142eSMartin Matuska #endif /* HAVE_MKSTEMP */ 465*6c95142eSMartin Matuska #endif /* !_WIN32 || __CYGWIN__ */ 466