summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2019-01-23 01:19:46 +0100
committerGravatar Nikias Bassen2019-01-23 01:19:46 +0100
commita808accd1e748184933f0e4d97d499d79f34f889 (patch)
tree6635f67416e121c0ca9bb1b1feef3758c47b8a8a /src
parente0b44cfb99c7e400c0fc51474f240dba3facd412 (diff)
downloadidevicerestore-a808accd1e748184933f0e4d97d499d79f34f889.tar.gz
idevicerestore-a808accd1e748184933f0e4d97d499d79f34f889.tar.bz2
Replace tempnam() with mkstemp() and provide reference implementation for systems lacking it
Diffstat (limited to 'src')
-rw-r--r--src/common.c177
-rw-r--r--src/common.h2
-rw-r--r--src/idevicerestore.c2
-rw-r--r--src/restore.c13
4 files changed, 188 insertions, 6 deletions
diff --git a/src/common.c b/src/common.c
index c3d835f..59e37a5 100644
--- a/src/common.c
+++ b/src/common.c
@@ -28,10 +28,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <errno.h>
#include <libgen.h>
#include <time.h>
#include <sys/stat.h>
+#include <fcntl.h>
+
+#ifdef WIN32
+#include <windows.h>
+#ifndef _O_EXCL
+#define _O_EXCL 0x0400
+#endif
+#ifndef O_EXCL
+#define O_EXCL _O_EXCL
+#endif
+#else
+#include <sys/time.h>
+#include <pthread.h>
+#endif
#include "common.h"
@@ -280,6 +295,168 @@ int mkdir_with_parents(const char *dir, int mode)
return res;
}
+#ifndef HAVE_MKSTEMP
+/* Based on libc's __gen_tempname() from sysdeps/posix/tempname.c
+ Copyright (C) 1991-2018 Free Software Foundation, Inc.
+ With changes from https://stackoverflow.com/a/6036308 and some
+ additional changes. */
+int mkstemp(char *tmpl)
+{
+ static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ int len;
+ char *XXXXXX;
+ static unsigned long long value;
+ unsigned long long random_time_bits;
+ unsigned int count;
+ int fd = -1;
+ int save_errno = errno;
+
+ /* A lower bound on the number of temporary files to attempt to
+ generate. The maximum total number of temporary file names that
+ can exist for a given template is 62**6. It should never be
+ necessary to try all these combinations. Instead if a reasonable
+ number of names is tried (we define reasonable as 62**3) fail to
+ give the system administrator the chance to remove the problems. */
+#define ATTEMPTS_MIN (62 * 62 * 62)
+
+ /* The number of times to attempt to generate a temporary file. To
+ conform to POSIX, this must be no smaller than TMP_MAX. */
+#if ATTEMPTS_MIN < TMP_MAX
+ unsigned int attempts = TMP_MAX;
+#else
+ unsigned int attempts = ATTEMPTS_MIN;
+#endif
+
+ len = strlen (tmpl);
+ if (len < 6 || strcmp (&tmpl[len - 6], "XXXXXX"))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* This is where the Xs start. */
+ XXXXXX = &tmpl[len - 6];
+
+ /* Get some more or less random data. */
+#ifdef WIN32
+ {
+ SYSTEMTIME stNow;
+ FILETIME ftNow;
+
+ // get system time
+ GetSystemTime(&stNow);
+ if (!SystemTimeToFileTime(&stNow, &ftNow))
+ {
+ errno = -1;
+ return -1;
+ }
+
+ random_time_bits = (((unsigned long long)ftNow.dwHighDateTime << 32)
+ | (unsigned long long)ftNow.dwLowDateTime);
+ }
+ value += random_time_bits ^ ((unsigned long long)GetCurrentProcessId() << 32 | (unsigned long long)GetCurrentThreadId());
+#else
+ {
+ struct timeval tvNow = {0, 0};
+ gettimeofday(&tvNow, NULL);
+ random_time_bits = (((unsigned long long)tvNow.tv_sec << 32)
+ | (unsigned long long)tvNow.tv_usec);
+ }
+ value += random_time_bits ^ ((unsigned long long)getpid() << 32 | (unsigned long long)(uintptr_t)pthread_self());
+#endif
+
+ for (count = 0; count < attempts; value += 7777, ++count)
+ {
+ unsigned long long v = value;
+
+ /* Fill in the random bits. */
+ XXXXXX[0] = letters[v % 62];
+ v /= 62;
+ XXXXXX[1] = letters[v % 62];
+ v /= 62;
+ XXXXXX[2] = letters[v % 62];
+ v /= 62;
+ XXXXXX[3] = letters[v % 62];
+ v /= 62;
+ XXXXXX[4] = letters[v % 62];
+ v /= 62;
+ XXXXXX[5] = letters[v % 62];
+
+#ifdef WIN32
+ fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, _S_IREAD | _S_IWRITE);
+#else
+ fd = open (tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
+#endif
+ if (fd >= 0)
+ {
+ errno = save_errno;
+ return fd;
+ }
+ else if (errno != EEXIST)
+ return -1;
+ }
+
+ /* We got out of the loop because we ran out of combinations to try. */
+ errno = EEXIST;
+ return -1;
+}
+#endif
+
+char *get_temp_filename(const char *prefix)
+{
+ char *result = NULL;
+ char *tmpdir;
+ size_t lt;
+ size_t lp;
+ const char *TMPVARS[] = { "TMPDIR", "TMP", "TEMP", "TEMPDIR", NULL };
+ int i = 0;
+ int fd;
+
+ /* check the prefix parameter */
+ if (!prefix) {
+ prefix = "tmp_";
+ }
+#ifdef WIN32
+ if (strchr(prefix, '/') || strchr(prefix, '\\')) return NULL;
+#else
+ if (strchr(prefix, '/')) return NULL;
+#endif
+
+ while (TMPVARS[i] && ((tmpdir = getenv(TMPVARS[i])) == NULL)) i++;
+ if (!tmpdir || access(tmpdir, W_OK|X_OK) != 0) {
+#ifdef WIN32
+ tmpdir = "C:\\WINDOWS\\TEMP";
+#else
+ tmpdir = P_tmpdir;
+#endif
+ }
+ if (!tmpdir || access(tmpdir, W_OK|X_OK) != 0) {
+ return NULL;
+ }
+
+ lt = strlen(tmpdir);
+ if (lt < 1) {
+ return NULL;
+ }
+ lp = strlen(prefix);
+ result = malloc(lt + lp + 8);
+ strncpy(result, tmpdir, lt);
+#ifdef WIN32
+ if (tmpdir[lt-1] != '/' && tmpdir[lt-1] != '\\') result[lt++] = '\\';
+#else
+ if (tmpdir[lt-1] != '/') result[lt++] = '/';
+#endif
+ strncpy(result + lt, prefix, lp);
+ strcpy(result + lt + lp, "XXXXXX");
+ fd = mkstemp(result);
+ if (fd < 0) {
+ free(result);
+ result = NULL;
+ }
+ close(fd);
+ return result;
+}
+
void idevicerestore_progress(struct idevicerestore_client_t* client, int step, double progress)
{
if(client && client->progress_cb) {
diff --git a/src/common.h b/src/common.h
index efa94f9..2f6beb3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -136,6 +136,8 @@ char *generate_guid(void);
int mkdir_with_parents(const char *dir, int mode);
+char *get_temp_filename(const char *prefix);
+
void idevicerestore_progress(struct idevicerestore_client_t* client, int step, double progress);
#ifndef HAVE_STRSEP
diff --git a/src/idevicerestore.c b/src/idevicerestore.c
index 3a496de..822601c 100644
--- a/src/idevicerestore.c
+++ b/src/idevicerestore.c
@@ -629,7 +629,7 @@ int idevicerestore_start(struct idevicerestore_client_t* client)
unlock_file(&li);
if (!extf) {
// use temp filename
- filesystem = tempnam(NULL, "ipsw_");
+ filesystem = get_temp_filename("ipsw_");
if (!filesystem) {
error("WARNING: Could not get temporary filename, using '%s' in current directory\n", fsname);
filesystem = strdup(fsname);
diff --git a/src/restore.c b/src/restore.c
index 6652aa0..a187dfa 100644
--- a/src/restore.c
+++ b/src/restore.c
@@ -1627,15 +1627,18 @@ int restore_send_baseband_data(restored_client_t restore, struct idevicerestore_
}
// extract baseband firmware to temp file
- bbfwtmp = tempnam(NULL, client->udid);
+ bbfwtmp = get_temp_filename("bbfw_");
if (!bbfwtmp) {
- error("WARNING: Could not generate temporary filename, using bbfw.tmp\n");
- bbfwtmp = strdup("bbfw.tmp");
+ size_t l = strlen(client->udid);
+ bbfwtmp = malloc(l + 10);
+ strcpy(bbfwtmp, "bbfw_");
+ strncpy(bbfwtmp + 5, client->udid, l);
+ strcpy(bbfwtmp + 5 + l, ".tmp");
+ error("WARNING: Could not generate temporary filename, using %s in current directory\n", bbfwtmp);
}
if (ipsw_extract_to_file(client->ipsw, bbfwpath, bbfwtmp) != 0) {
error("ERROR: Unable to extract baseband firmware from ipsw\n");
- plist_free(response);
- return -1;
+ goto leave;
}
if (bb_nonce && !client->restore->bbtss) {