Beispiel #1
0
HFSPlusCatalogRecord* getLinkTarget(HFSPlusCatalogRecord* record, HFSCatalogNodeID parentID, HFSPlusCatalogKey *key, Volume* volume) {
	io_func* io;
	char pathBuffer[1024];
	HFSPlusCatalogRecord* toReturn;
	HFSPlusCatalogKey nkey;
	int exact;

	if(record->recordType == kHFSPlusFileRecord && (((HFSPlusCatalogFile*)record)->permissions.fileMode & S_IFLNK) == S_IFLNK) {
		io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &(((HFSPlusCatalogFile*)record)->dataFork), record, volume);
		READ(io, 0, (((HFSPlusCatalogFile*)record)->dataFork).logicalSize, pathBuffer);
		CLOSE(io);
		pathBuffer[(((HFSPlusCatalogFile*)record)->dataFork).logicalSize] = '\0';
		toReturn = getRecordFromPath3(pathBuffer, volume, NULL, key, TRUE, TRUE, parentID);
		free(record);
		return toReturn;
	} else if(record->recordType == kHFSPlusFileRecord && (((HFSPlusCatalogFile*)record)->userInfo.fileType) == kHardLinkFileType) {
		sprintf(pathBuffer, "iNode%d", ((HFSPlusCatalogFile*)record)->permissions.special.iNodeNum);
		nkey.parentID = volume->metadataDir;
    		ASCIIToUnicode(pathBuffer, &nkey.nodeName); 
		nkey.keyLength = sizeof(nkey.parentID) + sizeof(nkey.nodeName.length) + (sizeof(uint16_t) * nkey.nodeName.length);

		toReturn = (HFSPlusCatalogRecord*) search(volume->catalogTree, (BTKey*)(&nkey), &exact, NULL, NULL);

		free(record);

		return toReturn;
	} else {
		return record;
	}
}
Beispiel #2
0
int makeSymlink(const char* pathName, const char* target, Volume* volume) {
	io_func* io;
	HFSPlusCatalogFile* record;

	record = (HFSPlusCatalogFile*) getRecordFromPath3(pathName, volume, NULL, NULL, TRUE, FALSE, kHFSRootFolderID);

	if(!record) {
		newFile(pathName, volume);
		record = (HFSPlusCatalogFile*) getRecordFromPath(pathName, volume, NULL, NULL);
		if(!record) {
			return FALSE;
		}
		record->permissions.fileMode |= S_IFLNK;
		record->userInfo.fileType = kSymLinkFileType;
		record->userInfo.fileCreator = kSymLinkCreator;
		updateCatalog(volume, (HFSPlusCatalogRecord*) record);
	} else {
		if(record->recordType != kHFSPlusFileRecord || (((HFSPlusCatalogFile*)record)->permissions.fileMode & S_IFLNK) != S_IFLNK) {
			free(record);
			return FALSE;
		}
	}

	io = openRawFile(record->fileID, &record->dataFork, (HFSPlusCatalogRecord*) record, volume);
	WRITE(io, 0, strlen(target), (void*) target);
	CLOSE(io);
	free(record);

	return TRUE;
}
Beispiel #3
0
HFSPlusCatalogRecord* getLinkTarget(HFSPlusCatalogRecord* record, HFSCatalogNodeID parentID, HFSPlusCatalogKey *key, Volume* volume) {
	io_func* io;
	char pathBuffer[1024];
	HFSPlusCatalogRecord* toReturn;

	if(record->recordType == kHFSPlusFileRecord && (((HFSPlusCatalogFile*)record)->permissions.fileMode & S_IFLNK) == S_IFLNK) {
		io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &(((HFSPlusCatalogFile*)record)->dataFork), record, volume);
		READ(io, 0, (((HFSPlusCatalogFile*)record)->dataFork).logicalSize, pathBuffer);
		CLOSE(io);
		pathBuffer[(((HFSPlusCatalogFile*)record)->dataFork).logicalSize] = '\0';
		toReturn = getRecordFromPath3(pathBuffer, volume, NULL, key, TRUE, TRUE, parentID);
		free(record);
		return toReturn;
	} else {
		return record;
	}
}
Beispiel #4
0
int removeFile(const char* fileName, Volume* volume) {
	HFSPlusCatalogRecord* record;
	HFSPlusCatalogKey key;
	io_func* io;
	HFSPlusCatalogFolder* parentFolder = NULL;

	record = getRecordFromPath3(fileName, volume, NULL, &key, TRUE, FALSE, kHFSRootFolderID);
	if(record != NULL) {
		parentFolder = (HFSPlusCatalogFolder*) getRecordByCNID(key.parentID, volume);
		if(parentFolder != NULL) {
			if(parentFolder->recordType != kHFSPlusFolderRecord) {
				ASSERT(FALSE, "parent not folder");
				free(parentFolder);
				return FALSE;
			}
		} else {
			ASSERT(FALSE, "can't find parent");
			return FALSE;
		}

		if(record->recordType == kHFSPlusFileRecord) {
			XAttrList* next, *attrs;
			io = openRawFile(((HFSPlusCatalogFile*)record)->fileID, &((HFSPlusCatalogFile*)record)->dataFork, record, volume);
			allocate((RawFile*)io->data, 0);
			CLOSE(io);

			removeFromBTree(volume->catalogTree, (BTKey*)(&key));
			
			attrs = getAllExtendedAttributes(((HFSPlusCatalogFile*)record)->fileID, volume);
			if(attrs != NULL) {
				while(attrs != NULL) {
					next = attrs->next;
					unsetAttribute(volume, ((HFSPlusCatalogFile*)record)->fileID, attrs->name);
					free(attrs->name);
					free(attrs);
					attrs = next;
				}	
			}	


			key.nodeName.length = 0;
			key.parentID = ((HFSPlusCatalogFile*)record)->fileID;
			key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length);
			removeFromBTree(volume->catalogTree, (BTKey*)(&key));

			volume->volumeHeader->fileCount--;
		} else {
			if(((HFSPlusCatalogFolder*)record)->valence > 0) {
				free(record);
				free(parentFolder);
				ASSERT(FALSE, "folder not empty");
				return FALSE;
			} else {
				XAttrList *next, *attrs;
				removeFromBTree(volume->catalogTree, (BTKey*)(&key));
				attrs = getAllExtendedAttributes(((HFSPlusCatalogFolder*)record)->folderID, volume);
				if(attrs != NULL) {
					while(attrs != NULL) {
						next = attrs->next;
						unsetAttribute(volume, ((HFSPlusCatalogFolder*)record)->folderID, attrs->name);
						free(attrs->name);
						free(attrs);
						attrs = next;
					}	
				}	

				key.nodeName.length = 0;
				key.parentID = ((HFSPlusCatalogFolder*)record)->folderID;
				key.keyLength = sizeof(key.parentID) + sizeof(key.nodeName.length);
				removeFromBTree(volume->catalogTree, (BTKey*)(&key));
			}

			parentFolder->folderCount--;
			volume->volumeHeader->folderCount--;
		}
		parentFolder->valence--;
		updateCatalog(volume, (HFSPlusCatalogRecord*) parentFolder);
		updateVolume(volume);

		free(record);
		free(parentFolder);

		return TRUE;
	} else {
		if(parentFolder)
			free(parentFolder);
		ASSERT(FALSE, "cannot find record");
		return FALSE;
	}
}
Beispiel #5
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;
}
Beispiel #6
0
HFSPlusCatalogRecord* getRecordFromPath2(const char* path, Volume* volume, char **name, HFSPlusCatalogKey* retKey, char traverse) {
	return getRecordFromPath3(path, volume, name, retKey, TRUE, TRUE, kHFSRootFolderID);
}
Beispiel #7
0
void hfs_untar(Volume* volume, AbstractFile* tarFile) {
	size_t tarSize = tarFile->getLength(tarFile);
	size_t curRecord = 0;
	char block[512];

	while(curRecord < tarSize) {
		tarFile->seek(tarFile, curRecord);
		tarFile->read(tarFile, block, 512);

		uint32_t mode = 0;
		char* fileName = NULL;
		const char* target = NULL;
		uint32_t type = 0;
		uint32_t size;
		uint32_t uid;
		uint32_t gid;

		sscanf(&block[100], "%o", &mode);
		fileName = &block[0];
		sscanf(&block[156], "%o", &type);
		target = &block[157];
		sscanf(&block[124], "%o", &size);
		sscanf(&block[108], "%o", &uid);
		sscanf(&block[116], "%o", &gid);

		if(fileName[0] == '\0')
			break;

		if(fileName[0] == '.' && fileName[1] == '/') {
			fileName += 2;
		}

		if(fileName[0] == '\0')
			goto loop;

		if(fileName[strlen(fileName) - 1] == '/')
			fileName[strlen(fileName) - 1] = '\0';

		HFSPlusCatalogRecord* record = getRecordFromPath3(fileName, volume, NULL, NULL, TRUE, FALSE, kHFSRootFolderID);
		if(record) {
			if(record->recordType == kHFSPlusFolderRecord || type == 5) {
				if(!silence)
					printf("ignoring %s, type = %d\n", fileName, type);
				free(record);
				goto loop;
			} else {
				printf("replacing %s\n", fileName);
				free(record);
				removeFile(fileName, volume);
			}
		}

		if(type == 0) {
			if(!silence)
				printf("file: %s (%04o), size = %d\n", fileName, mode, size);
			void* buffer = malloc(size);
			tarFile->seek(tarFile, curRecord + 512);
			tarFile->read(tarFile, buffer, size);
			AbstractFile* inFile = createAbstractFileFromMemory(&buffer, size);
			add_hfs(volume, inFile, fileName);
			free(buffer);
		} else if(type == 5) {
			if(!silence)
				printf("directory: %s (%04o)\n", fileName, mode);
			newFolder(fileName, volume);
		} else if(type == 2) {
			if(!silence)
				printf("symlink: %s (%04o) -> %s\n", fileName, mode, target);
			makeSymlink(fileName, target, volume);
		}

		chmodFile(fileName, mode, volume);
		chownFile(fileName, uid, gid, volume);

loop:

		curRecord = (curRecord + 512) + ((size + 511) / 512 * 512);
	}

}