Пример #1
0
static BTKey* catalogDataRead(off_t offset, io_func* io) {
  int16_t recordType;
  HFSPlusCatalogRecord* record;
  uint16_t nameLength;
  
  if(!READ(io, offset, sizeof(int16_t), &recordType))
    return NULL;
    
  FLIPENDIAN(recordType); fflush(stdout);

  switch(recordType) {
    case kHFSPlusFolderRecord:
      record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogFolder));
      if(!READ(io, offset, sizeof(HFSPlusCatalogFolder), record))
        return NULL;
      flipCatalogFolder((HFSPlusCatalogFolder*)record);
      break;
      
    case kHFSPlusFileRecord:
      record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogFile));
      if(!READ(io, offset, sizeof(HFSPlusCatalogFile), record))
        return NULL;
      flipCatalogFile((HFSPlusCatalogFile*)record);
      break;
      
    case kHFSPlusFolderThreadRecord:
    case kHFSPlusFileThreadRecord:
      record = (HFSPlusCatalogRecord*) malloc(sizeof(HFSPlusCatalogThread));
      
      if(!READ(io, offset + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t), sizeof(uint16_t), &nameLength))
        return NULL;

      FLIPENDIAN(nameLength);
      
      if(!READ(io, offset, sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * nameLength), record))
        return NULL;
      
      flipCatalogThread((HFSPlusCatalogThread*)record, FALSE);
      break;
  }

  return (BTKey*)record;
}
Пример #2
0
int move(const char* source, const char* dest, Volume* volume) {
  HFSPlusCatalogRecord* srcRec;
  HFSPlusCatalogFolder* srcFolderRec;
  HFSPlusCatalogFolder* destRec;
  char* destPath;
  char* destName;
  char* curChar;
  char* lastSeparator;
  
  int i;
  int threadLength;

  HFSPlusCatalogKey srcKey;
  HFSPlusCatalogKey destKey;
  HFSPlusCatalogThread* thread;
  
  srcRec = getRecordFromPath3(source, volume, NULL, &srcKey, TRUE, FALSE, kHFSRootFolderID);
  if(srcRec == NULL) {
    free(srcRec);
    return FALSE;
  }
  
  srcFolderRec = (HFSPlusCatalogFolder*) getRecordByCNID(srcKey.parentID, volume);
    
  if(srcFolderRec == NULL || srcFolderRec->recordType != kHFSPlusFolderRecord) {
    free(srcRec);
    free(srcFolderRec);
    return FALSE;
  }
    
  destPath = strdup(dest);
  
  curChar = destPath;
  lastSeparator = NULL;
  
  while((*curChar) != '\0') {
    if((*curChar) == '/')
      lastSeparator = curChar;
    curChar++;
  }
  
  if(lastSeparator == NULL) {
    destRec = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL);
    destName = destPath;
  } else {
    destName = lastSeparator + 1;
    *lastSeparator = '\0';
    destRec = (HFSPlusCatalogFolder*) getRecordFromPath(destPath, volume, NULL, NULL);
    
    if(destRec == NULL || destRec->recordType != kHFSPlusFolderRecord) {
      free(destPath);
      free(srcRec);
      free(destRec);
      free(srcFolderRec);
      return FALSE;
    }
  }
  
  removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey));
  
  srcKey.nodeName.length = 0;
  if(srcRec->recordType == kHFSPlusFolderRecord) {
    srcKey.parentID = ((HFSPlusCatalogFolder*)srcRec)->folderID;
  } else if(srcRec->recordType == kHFSPlusFileRecord) {
    srcKey.parentID = ((HFSPlusCatalogFile*)srcRec)->fileID;
  } else {
    /* unexpected */
    return FALSE;
  }
  srcKey.keyLength = sizeof(srcKey.parentID) + sizeof(srcKey.nodeName.length);
  
  removeFromBTree(volume->catalogTree, (BTKey*)(&srcKey));
  

  destKey.nodeName.length = strlen(destName);

  threadLength = sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length);
  thread = (HFSPlusCatalogThread*) malloc(threadLength);
  thread->reserved = 0;
  destKey.parentID = destRec->folderID;
  thread->parentID = destKey.parentID;  
  thread->nodeName.length = destKey.nodeName.length;
  for(i = 0; i < destKey.nodeName.length; i++) {
    destKey.nodeName.unicode[i] = destName[i];
    thread->nodeName.unicode[i] = destName[i];
  }
  
  destKey.keyLength = sizeof(uint32_t) + sizeof(uint16_t) + (sizeof(uint16_t) * destKey.nodeName.length);
  
  switch(srcRec->recordType) {
    case kHFSPlusFolderRecord:
      thread->recordType = kHFSPlusFolderThreadRecord;
      flipCatalogFolder((HFSPlusCatalogFolder*)srcRec);
      addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFolder), (unsigned char *)(srcRec));
      break;
      
    case kHFSPlusFileRecord:
      thread->recordType = kHFSPlusFileThreadRecord;
      flipCatalogFile((HFSPlusCatalogFile*)srcRec);
      addToBTree(volume->catalogTree, (BTKey*)(&destKey), sizeof(HFSPlusCatalogFile), (unsigned char *)(srcRec));
      break;
  }
  
  destKey.nodeName.length = 0;
  destKey.parentID = srcKey.parentID;
  destKey.keyLength = sizeof(destKey.parentID) + sizeof(destKey.nodeName.length);
  
  flipCatalogThread(thread, TRUE);
  addToBTree(volume->catalogTree, (BTKey*)(&destKey), threadLength, (unsigned char *)(thread));
    
  /* adjust valence */
  srcFolderRec->valence--;
  updateCatalog(volume, (HFSPlusCatalogRecord*) srcFolderRec);
  destRec->valence++;
  updateCatalog(volume, (HFSPlusCatalogRecord*) destRec);
  
  free(thread);
  free(destPath);
  free(srcRec);
  free(destRec);
  free(srcFolderRec);
      
  return TRUE;
}
Пример #3
0
HFSCatalogNodeID newFile(const char* pathName, Volume* volume) {
  HFSPlusCatalogFolder* parentFolder;
  HFSPlusCatalogFile file;
  HFSPlusCatalogKey key;
  HFSPlusCatalogThread thread;
  
  uint32_t newFileID;
  
  int threadLength;
  
  char* path;
  char* name;
  char* curChar;
  char* lastSeparator;
  
  path = strdup(pathName);
  
  curChar = path;
  lastSeparator = NULL;
  
  while((*curChar) != '\0') {
    if((*curChar) == '/')
      lastSeparator = curChar;
    curChar++;
  }
  
  if(lastSeparator == NULL) {
    parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath("/", volume, NULL, NULL);
    name = path;
  } else {
    name = lastSeparator + 1;
    *lastSeparator = '\0';
    parentFolder = (HFSPlusCatalogFolder*) getRecordFromPath(path, volume, NULL, NULL);
  }

  if(parentFolder == NULL || parentFolder->recordType != kHFSPlusFolderRecord) {
    free(path);
    free(parentFolder);
    return FALSE;
  }
  
  newFileID = volume->volumeHeader->nextCatalogID++;
  volume->volumeHeader->fileCount++;
  
  file.recordType = kHFSPlusFileRecord;
  file.flags = kHFSThreadExistsMask;
  file.reserved1 = 0;
  file.fileID = newFileID;
  file.createDate = UNIX_TO_APPLE_TIME(time(NULL));
  file.contentModDate = file.createDate;
  file.attributeModDate = file.createDate;
  file.accessDate = file.createDate;
  file.backupDate = file.createDate;
  file.permissions.ownerID = parentFolder->permissions.ownerID;
  file.permissions.groupID = parentFolder->permissions.groupID;
  file.permissions.adminFlags = 0;
  file.permissions.ownerFlags = 0;
  file.permissions.fileMode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
  file.permissions.special.iNodeNum = 0;
  memset(&file.userInfo, 0, sizeof(file.userInfo));
  memset(&file.finderInfo, 0, sizeof(file.finderInfo));
  file.textEncoding = 0;
  file.reserved2 = 0;
  memset(&file.dataFork, 0, sizeof(file.dataFork));
  memset(&file.resourceFork, 0, sizeof(file.resourceFork));
  
  key.parentID = parentFolder->folderID;
  ASCIIToUnicode(name, &key.nodeName);
  key.keyLength = sizeof(key.parentID) + STR_SIZE(key.nodeName);
  
  thread.recordType = kHFSPlusFileThreadRecord;
  thread.reserved = 0;
  thread.parentID = parentFolder->folderID;
  ASCIIToUnicode(name, &thread.nodeName);
  threadLength = sizeof(thread.recordType) + sizeof(thread.reserved) + sizeof(thread.parentID) + STR_SIZE(thread.nodeName);
  flipCatalogThread(&thread, TRUE);
  flipCatalogFile(&file);
  
  ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), sizeof(HFSPlusCatalogFile), (unsigned char *)(&file)), "addToBTree");
  key.nodeName.length = 0;
  key.parentID = newFileID;
  key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length);
  ASSERT(addToBTree(volume->catalogTree, (BTKey*)(&key), threadLength, (unsigned char *)(&thread)), "addToBTree");
  
  parentFolder->valence++;
  updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder);
  
  updateVolume(volume);
  
  free(parentFolder);
  free(path);
  
  return newFileID;
}