Esempio n. 1
0
SdErrorCode initCard() {
	if (!sd_raw_init()) {
		if (!sd_raw_available()) {
			reset();
			return SD_ERR_NO_CARD_PRESENT;
		} else {
			reset();
			return SD_ERR_INIT_FAILED;
		}
	} else if (!openPartition()) {
		reset();
		return SD_ERR_PARTITION_READ;
	} else if (!openFilesys()) {
		reset();
		return SD_ERR_OPEN_FILESYSTEM;
	} else if (!openRoot()) {
		reset();
		return SD_ERR_NO_ROOT;
		
	/* we need to keep locked as the last check */
	} else if (sd_raw_locked()) {
		return SD_ERR_CARD_LOCKED;
	}
	return SD_SUCCESS;
}
Esempio n. 2
0
ZExport (ZProfile &) ZProfile::getValues (ZStringlist & aList)
{
  ZFUNCTRACE_DEVELOP ("ZProfile::getValues(ZStringlist& aList)");
  aList.drop ();
#ifdef ZC_WIN
  openPath (zFalse);
  char buffer[MAX_PATH];
  long bufsize;
  for (unsigned long key = 0;; key++)
      {
        bufsize = sizeof (buffer);
        if (RegEnumValue ((HKEY) iPathHandle, key, buffer,
                          (LPDWORD) & bufsize, NULL, NULL, NULL,
                          NULL) != ERROR_SUCCESS)
          break;
        aList.addAsLast (buffer);
      }                         // for
#endif
#ifdef ZC_OS2
  if (!iPath.size ())
    return *this;               // os/2 has no values at this level

  openRoot ();

  // get size of list (not including the terminating 0)
  unsigned long size;
  if (!PrfQueryProfileSize (iRootHandle, iPath, 0, &size))
    throwSysErr (PrfQueryProfileSizeName);

  if (size)
      {
        // create buffer
        ZString buf (0, size++);

        // read list of values
        if (!PrfQueryProfileData (iRootHandle, iPath, 0, buf, &size))
          throwSysErr (PrfQueryProfileDataName);

        // parse values into stringlist
        char *s = buf;
        while (size)
            {
              ZString key;
              while (*s && size)
                  {
                    key += *s++;
                    size--;
                  }
              if (key.size ())
                aList.addAsLast (key);
              if (size)
                  {
                    s++;
                    size--;
                  }
            }                   // while
      }                         // if
#endif
  return *this;
}                               // getValues
Esempio n. 3
0
BlockId NodeSystem::cascadeUpdate(const FUSE::Path& path, BlockId newId) {
    printf("Performing cascade for path %s.\n", path.toString().c_str());

    std::stack<HandleRef> refStack;
    refStack.push(HandleRef(*this, openRoot()));

    for (size_t i = 1; i < path.size(); i++) {
        refStack.push(HandleRef(*this, openChild(refStack.top().get(), path.at(i - 1))));
    }

    BlockId blockId = newId;

    for (size_t i = 0; i < path.size(); i++) {
        const size_t pos = path.size() - i - 1;
        printf("Updating block ID for component %llu.\n",
               (unsigned long long) pos);
        printf("Updating block ID for component %llu: '%s'.\n",
               (unsigned long long) pos,
               path.at(pos).c_str());

        auto& parentNode = getNodeInfo(refStack.top().get()).node;
        Directory directory(parentNode);
        directory.updateChild(path.at(pos), blockId);

        parentNode.flush();

        blockId = parentNode.blockId();

        refStack.pop();
    }

    return blockId;
}
Esempio n. 4
0
void ScanGallery::openRoots()
{
   /* standard root always exists, ImgRoot creates it */
   KUrl rootUrl(KookaPref::galleryRoot());
   kDebug() << "Standard root" << rootUrl.url();

   m_defaultBranch = openRoot(rootUrl, i18n("Kooka Gallery"));
   m_defaultBranch->setOpen(true);

   /* open more configurable image repositories, configuration TODO */
   //openRoot(KUrl(getenv("HOME")), i18n("Home Directory"));
}
Esempio n. 5
0
void ZProfile::openPath (ZBoolean aCreate)
{
  ZFUNCTRACE_DEVELOP ("ZProfile::openPath(ZBoolean aCreate)");
  if (iPathHandle == 0 || (aCreate && iPathReadOnly))
      {
        closePath ();
        openRoot (aCreate);
        if (iPath.size ())
          iPathHandle = openHandle ((HKEY) iRootHandle, iPath, aCreate);
        else
          iPathHandle = iRootHandle;
        iPathReadOnly = !aCreate;
      }                         // if
}                               // openPath
Esempio n. 6
0
ZExport (ZProfile &) ZProfile::deleteValue (const ZString & aValueName)
{
  ZFUNCTRACE_DEVELOP ("ZProfile::deleteValue(const ZString& aValueName)");
#ifdef ZC_WIN
  openPath (zFalse);
  RegDeleteValue ((HKEY) iPathHandle, aValueName);
#endif
#ifdef ZC_OS2
  if (!iPath.size ())
    ZTHROWEXC (MissingPath);
  if (!aValueName.size ())
    ZTHROWEXC (MissingValueName);
  openRoot ();
  if (!PrfWriteProfileString (iRootHandle, iPath, aValueName, 0))
    throwSysErr (PrfWriteProfileStringName);
#endif
  return *this;
}                               // deleteValue
Esempio n. 7
0
ZExport (ZBoolean) ZProfile::valueExists (const ZString & aValueName)
{
  ZFUNCTRACE_DEVELOP ("ZProfile::valueExists(const ZString& aValueName)");
#ifdef ZC_WIN
  try
  {
    openPath (zFalse);
  }
  catch (const ZException & exc)
  {
    return zFalse;
  }                             // catch
#endif
#ifdef ZC_OS2
  openRoot ();
#endif
  ZStringlist list;
  getValues (list);
  return list.find (aValueName) >= 0;
}                               // valueExists
Esempio n. 8
0
FileHDF5::FileHDF5(const string &name, FileMode mode, Compression compression, OpenFlags flags) {
    if (!fileExists(name)) {
        mode = FileMode::Overwrite;
    }
    this->mode = mode;
    this->compr = compression;
    //we want hdf5 to keep track of the order in which links were created so that
    //the order for indexed based accessors is stable cf. issue #387
    H5Object fcpl = H5Pcreate(H5P_FILE_CREATE);
    fcpl.check("Could not create file creation plist");
    HErr res = H5Pset_link_creation_order(fcpl.h5id(), H5P_CRT_ORDER_TRACKED|H5P_CRT_ORDER_INDEXED);
    res.check("Unable to create file (H5Pset_link_creation_order failed.)");
    unsigned int h5mode =  map_file_mode(mode);

    bool is_create = !fileExists(name) || h5mode == H5F_ACC_TRUNC;

    if (is_create) {
        hid = H5Fcreate(name.c_str(), h5mode, fcpl.h5id(), H5P_DEFAULT);
    } else {
        hid = H5Fopen(name.c_str(), h5mode, H5P_DEFAULT);
    }

    if (!H5Iis_valid(hid)) {
        throw H5Exception("Could not open/create file");
    }

    openRoot();

    if (is_create) {
        createHeader();
    } else if (!checkHeader(mode) && (flags & OpenFlags::Force) != OpenFlags::Force) {
        throw nix::InvalidFile("FileHDF5::open_existing!");
    }

    metadata = root.openGroup("metadata");
    data = root.openGroup("data");

    setCreatedAt();
    setUpdatedAt();
}
Esempio n. 9
0
ZExport (ZProfile &) ZProfile::deleteKey (const ZString & aKeyName)
{
  ZFUNCTRACE_DEVELOP ("ZProfile::deleteKey(const ZString& aKeyName)");
#ifdef ZC_WIN
  // delete all values and subkeys first
  ZString oldPath (iPath);
  try
  {
    setPath (iPath + (char) ZC_PATHSEPARATOR + aKeyName);
    openPath (zFalse);

    ZStringlist list;
    int i;

    // delete all values
    setValue (ZString ());      // just clear out default value
    getValues (list);
    for (i = 0; i < list.count (); i++)
      if (list[i].size ())
          {
            deleteValue (list[i]);
          }                     // if

    // delete all subkeys
    getKeys (list);
    for (i = 0; i < list.count (); i++)
      deleteKey (list[i]);
  }                             // try
  catch (const ZException & exc)
  {
    setPath (oldPath);
    throw;
  }                             // catch

  setPath (oldPath);
  openPath (zFalse);
  RegDeleteKey ((HKEY) iPathHandle, aKeyName);
#endif
#ifdef ZC_OS2
  if (iPath.size () && aKeyName.size ())
    return *this;               // no keys at this level

  openRoot ();

  if (!iPath.size () && !aKeyName.size ())
      {
        // delete all applications:

        // will only do this if not the system- or user profile!
        if (iRootHandle == HINI_SYSTEMPROFILE ||
            iRootHandle == HINI_USERPROFILE)
          return *this;

        ZStringlist apps;
        getKeys (apps);
        for (long i = 0; i < apps.count (); i++)
          if (!PrfWriteProfileString (iRootHandle, apps[i], 0, 0))
            throwSysErr (PrfWriteProfileStringName);
      }
  else
      {
        if (!PrfWriteProfileString (iRootHandle,
                                    iPath.size ()? iPath : aKeyName, 0, 0))
          throwSysErr (PrfWriteProfileStringName);
      }                         // if
#endif
  return *this;
}                               // deleteKey
Esempio n. 10
0
ZExport (ZProfile &) ZProfile::setValue (const ZString & aValue,
                                         const ZString & aValueName,
                                         int aType)
{
  ZFUNCTRACE_DEVELOP
    ("ZProfile::setValue(const ZString& aValue, const ZString& aValueName, int aType)");

  // find out type if auto
  if (aType == Auto)
      {
        ZString v (aValue);
        if (ZString (v.strip ().asLong ()) == v)
          aType = Integer;
        else
            {
              if (aValue.isPrintable ())
                aType = String;
              else
                aType = Binary;
            }                   // if
      }                         // if

#ifdef ZC_WIN
  long dataType;
  switch (aType)
      {
      case String:
        dataType = 1;           // String
        break;
      case Integer:
        return setValue (aValue.asLong (), aValueName);
      default:
        dataType = 3;           // Binary
      }                         // switch

  openPath (zTrue);

  if (valueExists (aValueName))
    deleteValue (aValueName);

  if (!RegSetValueEx ((HKEY) iPathHandle, aValueName, 0,
                      dataType, (LPBYTE) (const char *) aValue,
                      aValue.size ()) == ERROR_SUCCESS)
    throwSysErr (SRegSetValueEx);
#endif
#ifdef ZC_OS2
  if (!iPath.size ())
    ZTHROWEXC (MissingPath);
  if (!aValueName.size ())
    ZTHROWEXC (MissingValueName);
  openRoot ();

  switch (aType)
      {
      case String:
        if (!PrfWriteProfileString (iRootHandle, iPath, aValueName,
                                    ZString::exp (aValue)))
          throwSysErr (PrfWriteProfileStringName);
        break;
      case Integer:
        {
          ZString v (aValue);
          if (!PrfWriteProfileString (iRootHandle, iPath, aValueName,
                                      ZString (v.strip ().asLong ())))
            throwSysErr (PrfWriteProfileStringName);
          break;
        }                       // Integer
      default:
        {
          ZString val (aValue);
          if (!PrfWriteProfileData (iRootHandle, iPath, aValueName,
                                    (char *) val, val.size ()))
            throwSysErr (PrfWriteProfileDataName);
        }                       // default
      }                         // switch
#endif
  return *this;
}                               // setValue
Esempio n. 11
0
ZExport (ZString) ZProfile::value (const ZString & aValueName)
{
  ZFUNCTRACE_DEVELOP ("ZProfile::value(const ZString& aValueName)");
#ifdef ZC_WIN
  openPath (zFalse);

  DWORD dataType, size;
  if (!RegQueryValueEx ((HKEY) iPathHandle, aValueName, 0,
                        &dataType, NULL, &size) == ERROR_SUCCESS)
    ZTHROWEXC (ValueNotFound);

  if (size)
      {
        ZString str (0, size);
        RegQueryValueEx ((HKEY) iPathHandle, aValueName, 0,
                         NULL, (LPBYTE) (char *) str, (LPDWORD) & size);

        switch (dataType)
            {
            case 1:            // String
            case 2:            // ExpandString
            case 7:            // MultiString
              if (str.size () > 0 && str[str.size ()] == 0)
                return str.subString (1, str.size ());
            default:;
            }                   // switch
      }                         // if
#endif
#ifdef ZC_OS2
  if (!iPath.size ())
    ZTHROWEXC (MissingPath);
  if (!aValueName.size ())
    ZTHROWEXC (MissingValueName);
  openRoot ();

  // query size of data
  unsigned long size;
  if (!PrfQueryProfileSize (iRootHandle, iPath, aValueName, &size))
    throwSysErr (PrfQueryProfileSizeName);

  if (size > 0)
      {
        ZString buf (0, size++);

        // try to get as string first
        PrfQueryProfileString (iRootHandle, iPath, aValueName, "", buf, size);
        ERRORID err = WinGetLastError (iHab);
        if (err == 0)
            {
              if (buf[buf.size ()] == 0
                  && buf.subString (1, buf.size () - 1).isPrintable ())
                return buf.subString (1, buf.size () - 1);
              return buf;
            }                   // if

        if (ERRORIDERROR (err) != PMERR_INVALID_ASCIIZ)
          throwSysErr (PrfQueryProfileStringName);

        // try to get binary data
        if (!PrfQueryProfileData (iRootHandle, iPath, aValueName, buf, &size))
          throwSysErr (PrfQueryProfileDataName);
        return buf;
      }                         // if
#endif
  return ZString ();
}                               // value
Esempio n. 12
0
File: main.c Progetto: OPK/xpwn
int main(int argc, char* argv[]) {
    init_libxpwn();

    Dictionary* info;
    Dictionary* firmwarePatches;
    Dictionary* patchDict;
    ArrayValue* patchArray;

    void* buffer;

    StringValue* actionValue;
    StringValue* pathValue;

    StringValue* fileValue;

    StringValue* patchValue;
    char* patchPath;

    char* rootFSPathInIPSW;
    io_func* rootFS;
    Volume* rootVolume;
    size_t rootSize;
    size_t preferredRootSize = 0;
    size_t minimumRootSize = 0;

    char* ramdiskFSPathInIPSW;
    unsigned int ramdiskKey[16];
    unsigned int ramdiskIV[16];
    unsigned int* pRamdiskKey = NULL;
    unsigned int* pRamdiskIV = NULL;
    io_func* ramdiskFS;
    Volume* ramdiskVolume;

    char* updateRamdiskFSPathInIPSW = NULL;

    int i;

    OutputState* outputState;

    char* bundlePath;
    char* bundleRoot = "FirmwareBundles/";

    int mergePaths;
    char* outputIPSW;

    void* imageBuffer;
    size_t imageSize;

    AbstractFile* bootloader39 = NULL;
    AbstractFile* bootloader46 = NULL;
    AbstractFile* applelogo = NULL;
    AbstractFile* recoverymode = NULL;

    char noWipe = FALSE;

    char unlockBaseband = FALSE;
    char selfDestruct = FALSE;
    char use39 = FALSE;
    char use46 = FALSE;
    char doBootNeuter = FALSE;
    char updateBB = FALSE;
    char useMemory = FALSE;

    unsigned int key[16];
    unsigned int iv[16];

    unsigned int* pKey = NULL;
    unsigned int* pIV = NULL;

    if(argc < 3) {
        XLOG(0, "usage %s <input.ipsw> <target.ipsw> [-b <bootimage.png>] [-r <recoveryimage.png>] [-s <system partition size>] [-memory] [-bbupdate] [-nowipe] [-e \"<action to exclude>\"] [[-unlock] [-use39] [-use46] [-cleanup] -3 <bootloader 3.9 file> -4 <bootloader 4.6 file>] <package1.tar> <package2.tar>...\n", argv[0]);
        return 0;
    }

    outputIPSW = argv[2];

    int* toRemove = NULL;
    int numToRemove = 0;

    for(i = 3; i < argc; i++) {
        if(argv[i][0] != '-') {
            break;
        }

        if(strcmp(argv[i], "-memory") == 0) {
            useMemory = TRUE;
            continue;
        }

        if(strcmp(argv[i], "-s") == 0) {
            int size;
            sscanf(argv[i + 1], "%d", &size);
            preferredRootSize = size;
            i++;
            continue;
        }

        if(strcmp(argv[i], "-nowipe") == 0) {
            noWipe = TRUE;
            continue;
        }

        if(strcmp(argv[i], "-bbupdate") == 0) {
            updateBB = TRUE;
            continue;
        }

        if(strcmp(argv[i], "-e") == 0) {
            numToRemove++;
            toRemove = realloc(toRemove, numToRemove * sizeof(int));
            toRemove[numToRemove - 1] = i + 1;
            i++;
            continue;
        }

        if(strcmp(argv[i], "-unlock") == 0) {
            unlockBaseband = TRUE;
            continue;
        }

        if(strcmp(argv[i], "-cleanup") == 0) {
            selfDestruct = TRUE;
            continue;
        }

        if(strcmp(argv[i], "-use39") == 0) {
            if(use46) {
                XLOG(0, "error: select only one of -use39 and -use46\n");
                exit(1);
            }
            use39 = TRUE;
            continue;
        }

        if(strcmp(argv[i], "-use46") == 0) {
            if(use39) {
                XLOG(0, "error: select only one of -use39 and -use46\n");
                exit(1);
            }
            use46 = TRUE;
            continue;
        }

        if(strcmp(argv[i], "-b") == 0) {
            applelogo = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
            if(!applelogo) {
                XLOG(0, "cannot open %s\n", argv[i + 1]);
                exit(1);
            }
            i++;
            continue;
        }

        if(strcmp(argv[i], "-r") == 0) {
            recoverymode = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
            if(!recoverymode) {
                XLOG(0, "cannot open %s\n", argv[i + 1]);
                exit(1);
            }
            i++;
            continue;
        }

        if(strcmp(argv[i], "-3") == 0) {
            bootloader39 = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
            if(!bootloader39) {
                XLOG(0, "cannot open %s\n", argv[i + 1]);
                exit(1);
            }
            i++;
            continue;
        }

        if(strcmp(argv[i], "-4") == 0) {
            bootloader46 = createAbstractFileFromFile(fopen(argv[i + 1], "rb"));
            if(!bootloader46) {
                XLOG(0, "cannot open %s\n", argv[i + 1]);
                exit(1);
            }
            i++;
            continue;
        }
    }

    mergePaths = i;

    if(use39 || use46 || unlockBaseband || selfDestruct || bootloader39 || bootloader46) {
        if(!(bootloader39) || !(bootloader46)) {
            XLOG(0, "error: you must specify both bootloader files.\n");
            exit(1);
        } else {
            doBootNeuter = TRUE;
        }
    }

    info = parseIPSW2(argv[1], bundleRoot, &bundlePath, &outputState, useMemory);
    if(info == NULL) {
        XLOG(0, "error: Could not load IPSW\n");
        exit(1);
    }

    firmwarePatches = (Dictionary*)getValueByKey(info, "FilesystemPatches");

    int j;
    for(j = 0; j < numToRemove; j++) {
        removeKey(firmwarePatches, argv[toRemove[j]]);
    }
    free(toRemove);

    firmwarePatches = (Dictionary*)getValueByKey(info, "FirmwarePatches");
    patchDict = (Dictionary*) firmwarePatches->values;
    while(patchDict != NULL) {
        fileValue = (StringValue*) getValueByKey(patchDict, "File");

        StringValue* keyValue = (StringValue*) getValueByKey(patchDict, "Key");
        StringValue* ivValue = (StringValue*) getValueByKey(patchDict, "IV");
        pKey = NULL;
        pIV = NULL;

        if(keyValue) {
            sscanf(keyValue->value, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
                   &key[0], &key[1], &key[2], &key[3], &key[4], &key[5], &key[6], &key[7], &key[8],
                   &key[9], &key[10], &key[11], &key[12], &key[13], &key[14], &key[15]);

            pKey = key;
        }

        if(ivValue) {
            sscanf(ivValue->value, "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
                   &iv[0], &iv[1], &iv[2], &iv[3], &iv[4], &iv[5], &iv[6], &iv[7], &iv[8],
                   &iv[9], &iv[10], &iv[11], &iv[12], &iv[13], &iv[14], &iv[15]);
            pIV = iv;
        }

        if(strcmp(patchDict->dValue.key, "Restore Ramdisk") == 0) {
            ramdiskFSPathInIPSW = fileValue->value;
            if(pKey) {
                memcpy(ramdiskKey, key, sizeof(key));
                memcpy(ramdiskIV, iv, sizeof(iv));
                pRamdiskKey = ramdiskKey;
                pRamdiskIV = ramdiskIV;
            } else {
                pRamdiskKey = NULL;
                pRamdiskIV = NULL;
            }
        }

        if(strcmp(patchDict->dValue.key, "Update Ramdisk") == 0) {
            updateRamdiskFSPathInIPSW = fileValue->value;
        }

        patchValue = (StringValue*) getValueByKey(patchDict, "Patch2");
        if(patchValue) {
            if(noWipe) {
                XLOG(0, "%s: ", patchDict->dValue.key);
                fflush(stdout);
                doPatch(patchValue, fileValue, bundlePath, &outputState, pKey, pIV, useMemory);
                patchDict = (Dictionary*) patchDict->dValue.next;
                continue; /* skip over the normal Patch */
            }
        }

        patchValue = (StringValue*) getValueByKey(patchDict, "Patch");
        if(patchValue) {
            XLOG(0, "%s: ", patchDict->dValue.key);
            fflush(stdout);
            doPatch(patchValue, fileValue, bundlePath, &outputState, pKey, pIV, useMemory);
        }

        if(strcmp(patchDict->dValue.key, "AppleLogo") == 0 && applelogo) {
            XLOG(0, "replacing %s\n", fileValue->value);
            fflush(stdout);
            ASSERT((imageBuffer = replaceBootImage(getFileFromOutputState(&outputState, fileValue->value), pKey, pIV, applelogo, &imageSize)) != NULL, "failed to use new image");
            addToOutput(&outputState, fileValue->value, imageBuffer, imageSize);
        }

        if(strcmp(patchDict->dValue.key, "RecoveryMode") == 0 && recoverymode) {
            XLOG(0, "replacing %s\n", fileValue->value);
            fflush(stdout);
            ASSERT((imageBuffer = replaceBootImage(getFileFromOutputState(&outputState, fileValue->value), pKey, pIV, recoverymode, &imageSize)) != NULL, "failed to use new image");
            addToOutput(&outputState, fileValue->value, imageBuffer, imageSize);
        }

        patchDict = (Dictionary*) patchDict->dValue.next;
    }

    fileValue = (StringValue*) getValueByKey(info, "RootFilesystem");
    rootFSPathInIPSW = fileValue->value;

    size_t defaultRootSize = ((IntegerValue*) getValueByKey(info, "RootFilesystemSize"))->value;
    minimumRootSize = defaultRootSize * 1000 * 1000;
    minimumRootSize -= minimumRootSize % 512;

    if(preferredRootSize == 0) {
        preferredRootSize = defaultRootSize;
    }

    rootSize =  preferredRootSize * 1000 * 1000;
    rootSize -= rootSize % 512;

    if(useMemory) {
        buffer = malloc(rootSize);
    } else {
        buffer = NULL;
    }

    if(buffer == NULL) {
        XLOG(2, "using filesystem backed temporary storage\n");
    }

    extractDmg(
        createAbstractFileFromFileVault(getFileFromOutputState(&outputState, rootFSPathInIPSW), ((StringValue*)getValueByKey(info, "RootFilesystemKey"))->value),
        openRoot((void**)&buffer, &rootSize), -1);


    rootFS = IOFuncFromAbstractFile(openRoot((void**)&buffer, &rootSize));
    rootVolume = openVolume(rootFS);
    XLOG(0, "Growing root to minimum: %ld\n", (long) defaultRootSize);
    fflush(stdout);
    grow_hfs(rootVolume, minimumRootSize);
    if(rootSize > minimumRootSize) {
        XLOG(0, "Growing root: %ld\n", (long) preferredRootSize);
        fflush(stdout);
        grow_hfs(rootVolume, rootSize);
    }

    firmwarePatches = (Dictionary*)getValueByKey(info, "FilesystemPatches");
    patchArray = (ArrayValue*) firmwarePatches->values;
    while(patchArray != NULL) {
        for(i = 0; i < patchArray->size; i++) {
            patchDict = (Dictionary*) patchArray->values[i];
            fileValue = (StringValue*) getValueByKey(patchDict, "File");

            actionValue = (StringValue*) getValueByKey(patchDict, "Action");
            if(strcmp(actionValue->value, "ReplaceKernel") == 0) {
                pathValue = (StringValue*) getValueByKey(patchDict, "Path");
                XLOG(0, "replacing kernel... %s -> %s\n", fileValue->value, pathValue->value);
                fflush(stdout);
                add_hfs(rootVolume, getFileFromOutputState(&outputState, fileValue->value), pathValue->value);
            }
            if(strcmp(actionValue->value, "Patch") == 0) {
                patchValue = (StringValue*) getValueByKey(patchDict, "Patch");
                patchPath = (char*) malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2));
                strcpy(patchPath, bundlePath);
                strcat(patchPath, "/");
                strcat(patchPath, patchValue->value);

                XLOG(0, "patching %s (%s)... ", fileValue->value, patchPath);
                doPatchInPlace(rootVolume, fileValue->value, patchPath);
                free(patchPath);
            }
        }

        patchArray = (ArrayValue*) patchArray->dValue.next;
    }

    for(; mergePaths < argc; mergePaths++) {
        XLOG(0, "merging %s\n", argv[mergePaths]);
        AbstractFile* tarFile = createAbstractFileFromFile(fopen(argv[mergePaths], "rb"));
        if(tarFile == NULL) {
            XLOG(1, "cannot find %s, make sure your slashes are in the right direction\n", argv[mergePaths]);
            releaseOutput(&outputState);
            closeRoot(buffer);
            exit(0);
        }
        hfs_untar(rootVolume, tarFile);
        tarFile->close(tarFile);
    }

    if(pRamdiskKey) {
        ramdiskFS = IOFuncFromAbstractFile(openAbstractFile2(getFileFromOutputStateForOverwrite(&outputState, ramdiskFSPathInIPSW), pRamdiskKey, pRamdiskIV));
    } else {
        XLOG(0, "unencrypted ramdisk\n");
        ramdiskFS = IOFuncFromAbstractFile(openAbstractFile(getFileFromOutputStateForOverwrite(&outputState, ramdiskFSPathInIPSW)));
    }
    ramdiskVolume = openVolume(ramdiskFS);
    XLOG(0, "growing ramdisk: %d -> %d\n", ramdiskVolume->volumeHeader->totalBlocks * ramdiskVolume->volumeHeader->blockSize, (ramdiskVolume->volumeHeader->totalBlocks + 4) * ramdiskVolume->volumeHeader->blockSize);
    grow_hfs(ramdiskVolume, (ramdiskVolume->volumeHeader->totalBlocks + 4) * ramdiskVolume->volumeHeader->blockSize);

    if(doBootNeuter) {
        firmwarePatches = (Dictionary*)getValueByKey(info, "BasebandPatches");
        if(firmwarePatches != NULL) {
            patchDict = (Dictionary*) firmwarePatches->values;
            while(patchDict != NULL) {
                pathValue = (StringValue*) getValueByKey(patchDict, "Path");

                fileValue = (StringValue*) getValueByKey(patchDict, "File");
                if(fileValue) {
                    XLOG(0, "copying %s -> %s... ", fileValue->value, pathValue->value);
                    fflush(stdout);
                    if(copyAcrossVolumes(ramdiskVolume, rootVolume, fileValue->value, pathValue->value)) {
                        patchValue = (StringValue*) getValueByKey(patchDict, "Patch");
                        if(patchValue) {
                            patchPath = malloc(sizeof(char) * (strlen(bundlePath) + strlen(patchValue->value) + 2));
                            strcpy(patchPath, bundlePath);
                            strcat(patchPath, "/");
                            strcat(patchPath, patchValue->value);
                            XLOG(0, "patching %s (%s)... ", pathValue->value, patchPath);
                            fflush(stdout);
                            doPatchInPlace(rootVolume, pathValue->value, patchPath);
                            free(patchPath);
                        }
                    }
                }

                if(strcmp(patchDict->dValue.key, "Bootloader 3.9") == 0 && bootloader39 != NULL) {
                    add_hfs(rootVolume, bootloader39, pathValue->value);
                }

                if(strcmp(patchDict->dValue.key, "Bootloader 4.6") == 0 && bootloader46 != NULL) {
                    add_hfs(rootVolume, bootloader46, pathValue->value);
                }

                patchDict = (Dictionary*) patchDict->dValue.next;
            }
        }

        fixupBootNeuterArgs(rootVolume, unlockBaseband, selfDestruct, use39, use46);
    }

    createRestoreOptions(ramdiskVolume, preferredRootSize, updateBB);
    closeVolume(ramdiskVolume);
    CLOSE(ramdiskFS);

    if(updateRamdiskFSPathInIPSW)
        removeFileFromOutputState(&outputState, updateRamdiskFSPathInIPSW);

    closeVolume(rootVolume);
    CLOSE(rootFS);

    buildDmg(openRoot((void**)&buffer, &rootSize), getFileFromOutputStateForReplace(&outputState, rootFSPathInIPSW));

    closeRoot(buffer);

    writeOutput(&outputState, outputIPSW);

    releaseDictionary(info);

    free(bundlePath);

    return 0;
}