From 4211f24424a4b22b5941a52e8acd988a500488ee Mon Sep 17 00:00:00 2001 From: Nikias Bassen Date: Mon, 16 Jul 2012 16:07:01 +0200 Subject: ipsw: implemented file locking for on-demand downloading --- src/Makefile.am | 2 +- src/ipsw.c | 15 ++++++++ src/locking.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/locking.h | 43 +++++++++++++++++++++ 4 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 src/locking.c create mode 100644 src/locking.h diff --git a/src/Makefile.am b/src/Makefile.am index c9f1313..53d2fda 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,7 +18,7 @@ AM_LDADD = $(AC_LDADD) bin_PROGRAMS = idevicerestore -idevicerestore_SOURCES = idevicerestore.c common.c tss.c img3.c ipsw.c normal.c dfu.c recovery.c restore.c asr.c libirecovery.c limera1n.c download.c +idevicerestore_SOURCES = idevicerestore.c common.c tss.c img3.c ipsw.c normal.c dfu.c recovery.c restore.c asr.c libirecovery.c limera1n.c download.c locking.c idevicerestore_CFLAGS = $(AM_CFLAGS) idevicerestore_LDFLAGS = $(AM_LDFLAGS) idevicerestore_LDADD = $(AM_LDADD) diff --git a/src/ipsw.c b/src/ipsw.c index 033b894..8e3d598 100644 --- a/src/ipsw.c +++ b/src/ipsw.c @@ -26,6 +26,7 @@ #include #include "ipsw.h" +#include "locking.h" #include "idevicerestore.h" #define BUFSIZE 0x100000 @@ -403,6 +404,15 @@ int ipsw_download_latest_fw(plist_t version_data, const char* product, const cha char fwlfn[256]; sprintf(fwlfn, "%s/%s", todir, fwfn); + char fwlock[256]; + sprintf(fwlock, "%s.lock", fwlfn); + + lock_info_t lockinfo; + + if (lock_file(fwlock, &lockinfo) != 0) { + error("WARNING: Could not lock file '%s'\n", fwlock); + } + int need_dl = 0; unsigned char zsha1[20] = {0, }; FILE* f = fopen(fwlfn, "rb"); @@ -452,5 +462,10 @@ int ipsw_download_latest_fw(plist_t version_data, const char* product, const cha if (res == 0) { *ipswfile = strdup(fwlfn); } + + if (unlock_file(&lockinfo) != 0) { + error("WARNING: Could not unlock file '%s'\n", fwlock); + } + return res; } diff --git a/src/locking.c b/src/locking.c new file mode 100644 index 0000000..dbbbd7c --- /dev/null +++ b/src/locking.c @@ -0,0 +1,116 @@ +/* + * locking.c + * locking extras + * + * Copyright (c) 2012 Nikias Bassen. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifdef WIN32 +#include +#else +#include +#endif + +#include "locking.h" +#include "common.h" + +int lock_file(const char* filename, lock_info_t* lockinfo) +{ + if (!lockinfo) { + return -1; + } +#ifdef WIN32 + lockinfo->fp = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (lockinfo->fp == INVALID_HANDLE_VALUE) { + debug("ERROR: could not open or create lockfile '%s'\n", filename); + return -1; + } + + lockinfo->ldata.Offset = 0; + lockinfo->ldata.OffsetHigh = 0; + + if (!LockFileEx(lockinfo->fp, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &lockinfo->ldata)) { + debug("ERROR: can't lock file, error %d\n", GetLastError()); + CloseHandle(lockinfo->fp); + lockinfo->fp = INVALID_HANDLE_VALUE; + return -1; + } +#else + lockinfo->fp = fopen(filename, "a+"); + + if (!lockinfo->fp) { + debug("ERROR: could not open or create lockfile '%s'\n", filename); + return -1; + } + + lockinfo->ldata.l_type = F_WRLCK; + lockinfo->ldata.l_whence = SEEK_SET; + lockinfo->ldata.l_start = 0; + lockinfo->ldata.l_len = 0; + + if (fcntl(fileno(lockinfo->fp), F_SETLKW, &lockinfo->ldata) < 0) { + debug("ERROR: can't lock file, error %d\n", errno); + fclose(lockinfo->fp); + lockinfo->fp = NULL; + return -1; + } +#endif + return 0; +} + +int unlock_file(lock_info_t* lockinfo) +{ + if (!lockinfo) { + return -1; + } +#ifdef WIN32 + if (lockinfo->fp == INVALID_HANDLE_VALUE) { + return -1; + } + + lockinfo->ldata.Offset = 0; + lockinfo->ldata.OffsetHigh = 0; + + if (!UnlockFileEx(lockinfo->fp, 0, 1, 0, &lockinfo->ldata)) { + debug("ERROR: can't unlock file, error %d\n", GetLastError()); + CloseHandle(lockinfo->fp); + lockinfo->fp = INVALID_HANDLE_VALUE; + return -1; + } + CloseHandle(lockinfo->fp); + lockinfo->fp = INVALID_HANDLE_VALUE; +#else + if (!lockinfo->fp) { + return -1; + } + + lockinfo->ldata.l_type = F_UNLCK; + lockinfo->ldata.l_whence = SEEK_SET; + lockinfo->ldata.l_start = 0; + lockinfo->ldata.l_len = 0; + + if (fcntl(fileno(lockinfo->fp), F_SETLK, &lockinfo->ldata) < 0) { + debug("ERROR: can't unlock file, error %d\n", errno); + fclose(lockinfo->fp); + lockinfo->fp = NULL; + return -1; + } + fclose(lockinfo->fp); + lockinfo->fp = NULL; +#endif + return 0; +} + diff --git a/src/locking.h b/src/locking.h new file mode 100644 index 0000000..9bde00b --- /dev/null +++ b/src/locking.h @@ -0,0 +1,43 @@ +/* + * locking.h + * locking extras header file + * + * Copyright (c) 2012 Nikias Bassen. All Rights Reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef LOCKING_H +#define LOCKING_H +#ifdef WIN32 +#include +#else +#include +#include +#endif + +typedef struct { +#ifdef WIN32 + HANDLE fp; + OVERLAPPED ldata; +#else + FILE* fp; + struct flock ldata; +#endif +} lock_info_t; + +int lock_file(const char* filename, lock_info_t* lockp); +int unlock_file(lock_info_t* lockp); + +#endif -- cgit v1.1-32-gdbae