示例#1
0
文件: hfs.c 项目: Conti/Chameleon
static long GetCatalogEntry(long long * dirIndex, char ** name,
                            long * flags, long * time,
                            FinderInfo * finderInfo, long * infoValid)
{
    long              extentSize, nodeSize, curNode, index;
    void              *extent;
    char              *nodeBuf, *testKey, *entry;
    BTNodeDescriptor  *node;

    if (gIsHFSPlus) {
        extent     = &gHFSPlus->catalogFile.extents;
        extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
    } else {
        extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
        extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
    }

    nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize);
    nodeBuf  = (char *)malloc(nodeSize);
    node     = (BTNodeDescriptor *)nodeBuf;

    index   = (long) (*dirIndex % nodeSize);
    curNode = (long) (*dirIndex / nodeSize);

    // Read the BTree node and get the record for index.
    ReadExtent(extent, extentSize, kHFSCatalogFileID,
               (long long) curNode * nodeSize, nodeSize, nodeBuf, 1);
    GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &entry);

    GetCatalogEntryInfo(entry, flags, time, finderInfo, infoValid);

    // Get the file name.
    if (gIsHFSPlus) {
        utf_encodestr(((HFSPlusCatalogKey *)testKey)->nodeName.unicode,
                      SWAP_BE16(((HFSPlusCatalogKey *)testKey)->nodeName.length),
                      (u_int8_t *)gTempStr, 256, OSBigEndian);
    } else {
        strncpy(gTempStr,
                (const char *)&((HFSCatalogKey *)testKey)->nodeName[1],
                 ((HFSCatalogKey *)testKey)->nodeName[0]);
        gTempStr[((HFSCatalogKey *)testKey)->nodeName[0]] = '\0';
    }
    *name = gTempStr;

    // Update dirIndex.
    index++;
    if (index == SWAP_BE16(node->numRecords)) {
        index = 0;
        curNode = SWAP_BE32(node->fLink);
    }
    *dirIndex = (long long) curNode * nodeSize + index;

    free(nodeBuf);

    return 0;
}
示例#2
0
long HFSReadFile(CICell ih, char * filePath, void *base, uint64_t offset,  uint64_t length)
{
    char entry[512];
    char devStr[12];
    long dirID, result, flags;

    if (HFSInitPartition(ih) == -1) return -1;

    dirID = kHFSRootFolderID;
    // Skip a lead '\'.  Start in the system folder if there are two.
    if (filePath[0] == '/') {
        if (filePath[1] == '/') {
            if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]);
            else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]);
            if (dirID == 0) {
		return -1;
	    }
            filePath++;
        }
        filePath++;
    }

    result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0);
    if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
	return -1;
    }

#if UNUSED
    // Not yet for Intel. System.config/Default.table will fail this check.
    // Check file owner and permissions.
    if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1;
#endif

    result = ReadFile(entry, &length, base, offset);
    if (result == -1) {
	return -1;
    }

    getDeviceDescription(ih, devStr);

    /*if (strstr(filePath, ".plist")) verbose("LoadConfig: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length);*/
    if (strstr(filePath, "com.apple.Boot.plist")) verbose("Config: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length);
    if (strstr(filePath, "theme.plist"))
    {
    	//valv: inspired from toitione's rtrim
    	int t_len = strlen(filePath) - 12;
    	char *themePath = strncpy(malloc(t_len + 1), filePath, t_len);
    	themePath[t_len+1] = '\0';
    	verbose("Theme: [%s]/%s\n", devStr, themePath);
    }
//    if (strstr(filePath, "theme.plist")) verbose("Theme: [%s].\n", devStr);
    if (strstr(filePath, "smbios.plist")) verbose("SMBios: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length);
    if (strstr(filePath, ".aml")) verbose("ACPI: [%s/%s] %d bytes.\n", devStr, filePath, (uint32_t)length);
    return length;
}
示例#3
0
static long CompareHFSPlusExtentsKeys(void * key, void * testKey)
{
	HFSPlusExtentKey	*searchKey, *trialKey;

	long			result;

	searchKey = key;
	trialKey  = testKey;

	// assume searchKey < trialKey
	result = -1;

	if (searchKey->fileID == trialKey->fileID)
	{
		// FileNum's are equal; compare fork types
		if (searchKey->forkType == trialKey->forkType)
		{
			// Fork types are equal; compare allocation block number
			if (searchKey->startBlock == trialKey->startBlock)
			{
				// Everything is equal
				result = 0;
			}
			else
			{
				// Allocation block numbers differ; determine sign
				if (SWAP_BE32(searchKey->startBlock) > SWAP_BE32(trialKey->startBlock))
				{
					result = 1;
				}
			}
		}
		else
		{
			// Fork types differ; determine sign
			if (searchKey->forkType > trialKey->forkType)
			{
				result = 1;
			}
		}
	}
	else
	{
		// FileNums differ; determine sign
		if (SWAP_BE32(searchKey->fileID) > SWAP_BE32(trialKey->fileID))
		{
			result = 1;
		}
	}

    return result;
}
示例#4
0
static long ResolvePathToCatalogEntry(char * filePath, long * flags,
                                      void * entry, long dirID, long long * dirIndex)
{
    char                 *restPath;
    long                 result, cnt, subFolderID = 0;
    long long tmpDirIndex;
    HFSPlusCatalogFile   *hfsPlusFile;

    // Copy the file name to gTempStr
    cnt = 0;
    while ((filePath[cnt] != '/') && (filePath[cnt] != '\0')) cnt++;
    strlcpy(gTempStr, filePath, cnt+1);

    // Move restPath to the right place.
    if (filePath[cnt] != '\0') cnt++;
    restPath = filePath + cnt;

    // gTempStr is a name in the current Dir.
    // restPath is the rest of the path if any.

    result = ReadCatalogEntry(gTempStr, dirID, entry, dirIndex);
    if (result == -1) {
	return -1;
    }

    GetCatalogEntryInfo(entry, flags, 0, 0, 0);

    if ((*flags & kFileTypeMask) == kFileTypeDirectory) {
        if (gIsHFSPlus)
            subFolderID = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->folderID);
        else
            subFolderID = SWAP_BE32(((HFSCatalogFolder *)entry)->folderID);
    }

    if ((*flags & kFileTypeMask) == kFileTypeDirectory)
        result = ResolvePathToCatalogEntry(restPath, flags, entry,
                                           subFolderID, dirIndex);

    if (gIsHFSPlus && ((*flags & kFileTypeMask) == kFileTypeFlat)) {
        hfsPlusFile = (HFSPlusCatalogFile *)entry;
        if ((SWAP_BE32(hfsPlusFile->userInfo.fdType) == kHardLinkFileType) &&
            (SWAP_BE32(hfsPlusFile->userInfo.fdCreator) == kHFSPlusCreator)) {
                sprintf(gLinkTemp, "%s/%s%ld", HFSPLUSMETADATAFOLDER,
                        HFS_INODE_PREFIX, SWAP_BE32(hfsPlusFile->bsdInfo.special.iNodeNum));
                result = ResolvePathToCatalogEntry(gLinkTemp, flags, entry,
                                                   kHFSRootFolderID, &tmpDirIndex);
        }
    }

    return result;
}
示例#5
0
/*
 * Create a new indirect link
 *
 * An indirect link is a reference to a data node.  The only useable
 * fields in the link are the link number, parentID, name and text
 * encoding.  All other catalog fields are ignored.
 */
static int
createindirectlink(struct hfsmount *hfsmp, u_int32_t linknum,
			u_int32_t linkparid, char *linkName, cnid_t *linkcnid)
{
	struct FndrFileInfo *fip;
	struct cat_desc desc;
	struct cat_attr attr;
	int result;

	/* Setup the descriptor */
	bzero(&desc, sizeof(desc));
	desc.cd_nameptr = linkName;
	desc.cd_namelen = strlen(linkName);
	desc.cd_parentcnid = linkparid;

	/* Setup the default attributes */
	bzero(&attr, sizeof(attr));
	
	/* links are matched to data nodes by link ID and to volumes by create date */
	attr.ca_rdev = linknum;  /* note: cat backend overloads ca_rdev to be the linknum when nlink = 0 */
	attr.ca_itime = HFSTOVCB(hfsmp)->vcbCrDate;
	attr.ca_mode = S_IFREG;

	fip = (struct FndrFileInfo *)&attr.ca_finderinfo;
	fip->fdType    = SWAP_BE32 (kHardLinkFileType);	/* 'hlnk' */
	fip->fdCreator = SWAP_BE32 (kHFSPlusCreator);	/* 'hfs+' */
	fip->fdFlags   = SWAP_BE16 (kHasBeenInited);

	hfs_global_shared_lock_acquire(hfsmp);
	if (hfsmp->jnl) {
	    if (journal_start_transaction(hfsmp->jnl) != 0) {
			hfs_global_shared_lock_release(hfsmp);
			return EINVAL;
	    }
	}

	/* Create the indirect link directly in the catalog */
	result = cat_create(hfsmp, &desc, &attr, NULL);

	if (result == 0 && linkcnid != NULL)
		*linkcnid = attr.ca_fileid;

	if (hfsmp->jnl) {
	    journal_end_transaction(hfsmp->jnl);
	}
	hfs_global_shared_lock_release(hfsmp);

	return (result);
}
示例#6
0
long HFSReadFile(CICell ih, char * filePath, void *base, uint64_t offset,  uint64_t length)
{
    char entry[512];
    char devStr[12];
    long dirID, result, flags = 0;
	
    if (HFSInitPartition(ih) == -1) return -1;
    
    dirID = kHFSRootFolderID;
    // Skip a lead '\'.  Start in the system folder if there are two.
    if (filePath[0] == '/') {
        if (filePath[1] == '/') {
            if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]);
            else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]);
            if (dirID == 0) {
				return -1;
			}
            filePath++;
        }
        filePath++;
    }
	
    result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0);
    if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
		return -1;
    }
	
#if UNUSED
    // Not yet for Intel. System.config/Default.table will fail this check.
    // Check file owner and permissions.
    if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1;
#endif
	
    result = ReadFile(entry, &length, base, offset);
    if (result == -1) {
		return -1;
    }
	
    getDeviceDescription(ih, devStr, sizeof(devStr));
	
	if (get_env(envHFSLoadVerbose)) {
		verbose("Read HFS%s file: [%s/%s] %d bytes.\n",
				(gIsHFSPlus ? "+" : ""), devStr, filePath, (uint32_t)length);
	} else if (get_env(envHFSLoadVerbose) == 0) {		
		safe_set_env(envHFSLoadVerbose, 1);
	}
    
    return length;
}
示例#7
0
void* FAST_FUNC try_to_mmap_module(const char *filename, size_t *image_size_p)
{
	/* We have user reports of failure to load 3MB module
	 * on a 16MB RAM machine. Apparently even a transient
	 * memory spike to 6MB during module load
	 * is too big for that system. */
	void *image;
	struct stat st;
	int fd;

	fd = xopen(filename, O_RDONLY);
	fstat(fd, &st);
	image = NULL;
	/* st.st_size is off_t, we can't just pass it to mmap */
	if (st.st_size <= *image_size_p) {
		size_t image_size = st.st_size;
		image = mmap(NULL, image_size, PROT_READ, MAP_PRIVATE, fd, 0);
		if (image == MAP_FAILED) {
			image = NULL;
		} else if (*(uint32_t*)image != SWAP_BE32(0x7f454C46)) {
			/* No ELF signature. Compressed module? */
			munmap(image, image_size);
			image = NULL;
		} else {
			/* Success. Report the size */
			*image_size_p = image_size;
		}
	}
	close(fd);
	return image;
}
示例#8
0
文件: hfs.c 项目: carriercomm/osx-2
void
HFSGetDescription(CICell ih, char *str, long strMaxLen)
{

    UInt16 nodeSize;
    UInt32 firstLeafNode;
    long dirIndex;
    char *name;
    long flags, time;

    if (HFSInitPartition(ih) == -1)  { return; }

    /* Fill some crucial data structures by side effect. */
    dirIndex = 0;
    HFSGetDirEntry(ih, "/", &dirIndex, &name, &flags, &time, 0, 0);

    /* Now we can loook up the volume name node. */
    nodeSize = SWAP_BE16(gBTHeaders[kBTreeCatalog]->nodeSize);
    firstLeafNode = SWAP_BE32(gBTHeaders[kBTreeCatalog]->firstLeafNode);

    dirIndex = firstLeafNode * nodeSize;

    GetCatalogEntry(&dirIndex, &name, &flags, &time, 0, 0);

    strncpy(str, name, strMaxLen);
    str[strMaxLen] = '\0';
}
示例#9
0
文件: hfs.c 项目: JayMonkey/chameleon
static long ReadFile(void * file, uint64_t * length, void * base, uint64_t offset)
{
	void			*extents;
	long			fileID;

	uint64_t		fileLength;

	HFSCatalogFile		*hfsFile = file;
	HFSPlusCatalogFile	*hfsPlusFile = file;

	if (gIsHFSPlus)
	{
		fileID  = SWAP_BE32(hfsPlusFile->fileID);
		fileLength = (uint64_t)SWAP_BE64(hfsPlusFile->dataFork.logicalSize);
		extents = &hfsPlusFile->dataFork.extents;
	}
	else
	{
		fileID  = SWAP_BE32(hfsFile->fileID);
		fileLength = SWAP_BE32(hfsFile->dataLogicalSize);
		extents = &hfsFile->dataExtents;
	}

	if (offset > fileLength)
	{
		printf("Offset is too large.\n");

		return -1;
	}

	if ((*length == 0) || ((offset + *length) > fileLength))
	{
		*length = fileLength - offset;
	}

/*
	if (*length > kLoadSize)
	{
		printf("File is too large.\n");
		return -1;
	}
*/

	*length = ReadExtent((char *)extents, fileLength, fileID, offset, *length, (char *)base, 0);

	return 0;
}
示例#10
0
/*
 * hfs_swap_HFSPlusForkData
 *
 *  There's still a few spots where we still need to swap the fork data.
 */
void
hfs_swap_HFSPlusForkData (
    HFSPlusForkData *src
)
{
    int i;

	src->logicalSize		= SWAP_BE64 (src->logicalSize);

	src->clumpSize			= SWAP_BE32 (src->clumpSize);
	src->totalBlocks		= SWAP_BE32 (src->totalBlocks);

    for (i = 0; i < kHFSPlusExtentDensity; i++) {
        src->extents[i].startBlock	= SWAP_BE32 (src->extents[i].startBlock);
        src->extents[i].blockCount	= SWAP_BE32 (src->extents[i].blockCount);
    }
}
示例#11
0
文件: hfs.c 项目: JayMonkey/chameleon
static long CompareHFSPlusCatalogKeys(void * key, void * testKey)
{
	HFSPlusCatalogKey *searchKey, *trialKey;
	long result, searchParentID, trialParentID;

	searchKey = key;
	trialKey  = testKey;

	searchParentID = SWAP_BE32(searchKey->parentID);
	trialParentID  = SWAP_BE32(trialKey->parentID);

	// parent dirID is unsigned
	if (searchParentID > trialParentID)
	{
		result = 1;
	}
	else if (searchParentID < trialParentID) 
	{
		result = -1;
	}
	else
	{
		// parent dirID's are equal, compare names
		if ((searchKey->nodeName.length == 0) || (trialKey->nodeName.length == 0))
		{
			result = searchKey->nodeName.length - trialKey->nodeName.length;
		}
		else if (gCaseSensitive)
		{
			result = BinaryUnicodeCompare(&searchKey->nodeName.unicode[0],
                                          SWAP_BE16(searchKey->nodeName.length),
                                          &trialKey->nodeName.unicode[0],
                                          SWAP_BE16(trialKey->nodeName.length));
		}
		else
		{
			result = FastUnicodeCompare(&searchKey->nodeName.unicode[0],
                                        SWAP_BE16(searchKey->nodeName.length),
                                        &trialKey->nodeName.unicode[0],
                                        SWAP_BE16(trialKey->nodeName.length), OSBigEndian);
		}
	}

	return result;
}
示例#12
0
文件: hfs.c 项目: carriercomm/osx-2
long
HFSGetFileBlock(CICell ih, char *filePath, unsigned long long *firstBlock)
{
    char entry[512];
    long dirID, result, flags;
    void               *extents;
    HFSCatalogFile     *hfsFile     = (void *)entry;
    HFSPlusCatalogFile *hfsPlusFile = (void *)entry;

    if (HFSInitPartition(ih) == -1) return -1;

    dirID = kHFSRootFolderID;
    // Skip a lead '\'.  Start in the system folder if there are two.
    if (filePath[0] == '/') {
        if (filePath[1] == '/') {
            if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]);
            else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]);
            if (dirID == 0) {
		return -1;
	    }
            filePath++;
        }
        filePath++;
    }

    result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0);
    if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
        printf("HFS: Resolve path %s failed\n", filePath);
	return -1;
    }

    if (gIsHFSPlus) {
        extents    = &hfsPlusFile->dataFork.extents;
    } else {
        extents    = &hfsFile->dataExtents;
    }

#if DEBUG
    printf("extent start 0x%x\n", (unsigned long)GetExtentStart(extents, 0));
    printf("block size 0x%x\n", (unsigned long)gBlockSize);
    printf("Allocation offset 0x%x\n", (unsigned long)gAllocationOffset);
#endif
    *firstBlock = ((unsigned long long)GetExtentStart(extents, 0) * (unsigned long long) gBlockSize + gAllocationOffset) / 512ULL;
    return 0;
}
/*
 * GNU tar uses "base-256 encoding" for very large numbers (>8 billion).
 * Encoding is binary, with highest bit always set as a marker
 * and sign in next-highest bit:
 * 80 00 .. 00 - zero
 * bf ff .. ff - largest positive number
 * ff ff .. ff - minus 1
 * c0 00 .. 00 - smallest negative number
 *
 * We expect it only in size field, where negative numbers don't make sense.
 */
static off_t getBase256_len12(const char *str)
{
	off_t value;
	int len;

	/* if (*str & 0x40) error; - caller prevents this */

	if (sizeof(off_t) >= 12) {
		/* Probably 128-bit (16 byte) off_t. Can be optimized. */
		len = 12;
		value = *str++ & 0x3f;
		while (--len)
			value = (value << 8) + (unsigned char) *str++;
		return value;
	}

#ifdef CHECK_FOR_OVERFLOW
	/* Can be optimized to eat 32-bit chunks */
	char c = *str++ & 0x3f;
	len = 12;
	while (1) {
		if (c)
			bb_error_msg_and_die("overflow in base-256 encoded file size");
		if (--len == sizeof(off_t))
			break;
		c = *str++;
	}
#else
	str += (12 - sizeof(off_t));
#endif

/* Now str points to sizeof(off_t) least significant bytes.
 *
 * Example of tar file with 8914993153 (0x213600001) byte file.
 * Field starts at offset 7c:
 * 00070  30 30 30 00 30 30 30 30  30 30 30 00 80 00 00 00  |000.0000000.....|
 * 00080  00 00 00 02 13 60 00 01  31 31 31 32 30 33 33 36  |.....`..11120336|
 *
 * str is at offset 80 or 84 now (64-bit or 32-bit off_t).
 * We (ab)use the fact that value happens to be aligned,
 * and fetch it in one go:
 */
	if (sizeof(off_t) == 8) {
		value = *(off_t*)str;
		value = SWAP_BE64(value);
	} else if (sizeof(off_t) == 4) {
		value = *(off_t*)str;
		value = SWAP_BE32(value);
	} else {
		value = 0;
		len = sizeof(off_t);
		while (--len)
			value = (value << 8) + (unsigned char) *str++;
	}
	return value;
}
示例#14
0
文件: hfs.c 项目: carriercomm/osx-2
static long ReadExtentsEntry(long fileID, long startBlock, void * entry)
{
    char             key[sizeof(HFSPlusExtentKey)];
    HFSExtentKey     *hfsKey     = (HFSExtentKey *)key;
    HFSPlusExtentKey *hfsPlusKey = (HFSPlusExtentKey *)key;

    // Make the extents key.
    if (gIsHFSPlus) {
        hfsPlusKey->forkType   = 0;
        hfsPlusKey->fileID     = SWAP_BE32(fileID);
        hfsPlusKey->startBlock = SWAP_BE32(startBlock);
    } else {
        hfsKey->forkType   = 0;
        hfsKey->fileID     = SWAP_BE32(fileID);
        hfsKey->startBlock = SWAP_BE16(startBlock);
    }

    return ReadBTreeEntry(kBTreeExtents, &key, entry, 0);
}
示例#15
0
文件: hfs.c 项目: carriercomm/osx-2
long HFSReadFile(CICell ih, char * filePath, void *base, unsigned long offset, unsigned long length)
{
    char entry[512];
    long dirID, result, flags;

    verbose("Loading HFS%s file: [%s] from %x.\n",
            (gIsHFSPlus ? "+" : ""), filePath, ih);

    if (HFSInitPartition(ih) == -1) return -1;

    dirID = kHFSRootFolderID;
    // Skip a lead '\'.  Start in the system folder if there are two.
    if (filePath[0] == '/') {
        if (filePath[1] == '/') {
            if (gIsHFSPlus) dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]);
            else dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]);
            if (dirID == 0) {
		return -1;
	    }
            filePath++;
        }
        filePath++;
    }

    result = ResolvePathToCatalogEntry(filePath, &flags, entry, dirID, 0);
    if ((result == -1) || ((flags & kFileTypeMask) != kFileTypeFlat)) {
	return -1;
    }

#if UNUSED
    // Not yet for Intel. System.config/Default.table will fail this check.
    // Check file owner and permissions.
    if (flags & (kOwnerNotRoot | kPermGroupWrite | kPermOtherWrite)) return -1;
#endif

    result = ReadFile(entry, &length, base, offset);
    if (result == -1) {
	return -1;
    }

    return length;
}
示例#16
0
文件: hfs.c 项目: carriercomm/osx-2
static long GetExtentStart(void * extents, long index)
{
    long                    start;
    HFSExtentDescriptor     *hfsExtents     = extents;
    HFSPlusExtentDescriptor *hfsPlusExtents = extents;

    if (gIsHFSPlus) start = SWAP_BE32(hfsPlusExtents[index].startBlock);
    else start = SWAP_BE16(hfsExtents[index].startBlock);

    return start;
}
示例#17
0
文件: hfs.c 项目: carriercomm/osx-2
static long GetExtentSize(void * extents, long index)
{
    long                    size;
    HFSExtentDescriptor     *hfsExtents     = extents;
    HFSPlusExtentDescriptor *hfsPlusExtents = extents;
  
    if (gIsHFSPlus) size = SWAP_BE32(hfsPlusExtents[index].blockCount);
    else size = SWAP_BE16(hfsExtents[index].blockCount);

    return size;
}
示例#18
0
文件: hfs.c 项目: carriercomm/osx-2
static long CompareHFSCatalogKeys(void * key, void * testKey)
{
    HFSCatalogKey *searchKey, *trialKey;
    long          result, searchParentID, trialParentID;

    searchKey = key;
    trialKey  = testKey;

    searchParentID = SWAP_BE32(searchKey->parentID);
    trialParentID  = SWAP_BE32(trialKey->parentID);

    // parent dirID is unsigned
    if (searchParentID > trialParentID)      result = 1;
    else if (searchParentID < trialParentID) result = -1;
    else {
        // parent dirID's are equal, compare names
        result = FastRelString(searchKey->nodeName, trialKey->nodeName);
    }

    return result;
}
示例#19
0
文件: hfs.c 项目: JayMonkey/chameleon
static long ReadCatalogEntry(char * fileName, long dirID, void * entry, long long * dirIndex)
{
	long              length = 0;
	char              key[sizeof(HFSPlusCatalogKey)];
	HFSCatalogKey     *hfsKey     = (HFSCatalogKey *)key;
	HFSPlusCatalogKey *hfsPlusKey = (HFSPlusCatalogKey *)key;

	// Make the catalog key.
	if (gIsHFSPlus)
	{
		hfsPlusKey->parentID = SWAP_BE32(dirID);
		length = strlen(fileName);

		if (length > 255)
		{
			length = 255;
		}

		utf_decodestr((u_int8_t *)fileName, hfsPlusKey->nodeName.unicode, &(hfsPlusKey->nodeName.length), 512, OSBigEndian);
	}
	else
	{
		hfsKey->parentID = SWAP_BE32(dirID);
		length = strlen(fileName);

		if (length > 31)
		{
			length = 31;
		}

		hfsKey->nodeName[0] = length;
		strncpy((char *)(hfsKey->nodeName + 1), fileName, length);
	}

	return ReadBTreeEntry(kBTreeCatalog, &key, entry, dirIndex);
}
示例#20
0
static u_int32_t GetExtentSize(void * extents, u_int32_t index)
{
	u_int32_t size = 0;

	HFSExtentDescriptor     *hfsExtents     = extents;
	HFSPlusExtentDescriptor *hfsPlusExtents = extents;

	if (gIsHFSPlus)
	{
		size = SWAP_BE32(hfsPlusExtents[index].blockCount);
	}
	else
	{
		size = SWAP_BE16(hfsExtents[index].blockCount);
	}

	return size;
}
示例#21
0
static u_int32_t GetExtentStart(void * extents, u_int32_t index)
{
	u_int32_t start;

	HFSExtentDescriptor		*hfsExtents		= extents;
	HFSPlusExtentDescriptor	*hfsPlusExtents	= extents;

	if (gIsHFSPlus)
	{
		start = SWAP_BE32(hfsPlusExtents[index].startBlock);
	}
	else
	{
		start = SWAP_BE16(hfsExtents[index].startBlock);
	}

	return start;
}
示例#22
0
文件: hfs.c 项目: JayMonkey/chameleon
long HFSGetDirEntry(CICell ih, char * dirPath, long long * dirIndex, char ** name, long * flags, long * time, FinderInfo * finderInfo, long * infoValid)
{
	char entry[512];

	long dirID, dirFlags = 0;

	if (HFSInitPartition(ih) == -1)
	{
		return -1;
	}

	if (*dirIndex == -1)
	{
		return -1;
	}

	dirID = kHFSRootFolderID;

	// Skip a lead '\'.  Start in the system folder if there are two.
	if (dirPath[0] == '/')
	{
		if (dirPath[1] == '/')
		{
			if (gIsHFSPlus)
			{
				dirID = SWAP_BE32(((long *)gHFSPlus->finderInfo)[5]);
			}
			else
			{
				dirID = SWAP_BE32(gHFSMDB->drFndrInfo[5]);
			}

			if (dirID == 0)
			{
				return -1;
			}

			dirPath++;
		}

		dirPath++;
	}

	if (*dirIndex == 0)
	{
		ResolvePathToCatalogEntry(dirPath, &dirFlags, entry, dirID, dirIndex);

		if (*dirIndex == 0)
		{
			*dirIndex = -1;
		}

		if ((dirFlags & kFileTypeMask) != kFileTypeUnknown)
		{
			return -1;
		}
	}

	GetCatalogEntry(dirIndex, name, flags, time, finderInfo, infoValid);

	if (*dirIndex == 0)
	{
		*dirIndex = -1;
	}

	if ((*flags & kFileTypeMask) == kFileTypeUnknown)
	{
		return -1;
	}

	return 0;
}
/*
_______________________________________________________________________

Routine:	BlockAllocateAny

Function:	Allocate one or more allocation blocks.  If there are fewer
			free blocks than requested, all free blocks will be
			allocated.  The caller guarantees that there is at least
			one free block.

Inputs:
	vcb				Pointer to volume where space is to be allocated
	startingBlock	Preferred first block for allocation
	endingBlock		Last block to check + 1
	maxBlocks		Maximum number of contiguous blocks to allocate
	useMetaZone

Outputs:
	actualStartBlock	First block of range allocated, or 0 if error
	actualNumBlocks		Number of blocks allocated, or 0 if error
_______________________________________________________________________
*/
static OSErr BlockAllocateAny(
	ExtendedVCB		*vcb,
	u_int32_t		startingBlock,
	register u_int32_t	endingBlock,
	u_int32_t		maxBlocks,
	Boolean			useMetaZone,
	u_int32_t		*actualStartBlock,
	u_int32_t		*actualNumBlocks)
{
	OSErr			err;
	register u_int32_t	block;			//	current block number
	register u_int32_t	currentWord;	//	Pointer to current word within bitmap block
	register u_int32_t	bitMask;		//	Word with given bits already set (ready to OR in)
	register u_int32_t	wordsLeft;		//	Number of words left in this bitmap block
	u_int32_t  *buffer = NULL;
	u_int32_t  *currCache = NULL;
	u_int32_t  blockRef;
	u_int32_t  bitsPerBlock;
	u_int32_t  wordsPerBlock;
	Boolean dirty = false;
	struct hfsmount *hfsmp = VCBTOHFS(vcb);

	/*
	 * When we're skipping the metadata zone and the start/end
	 * range overlaps with the metadata zone then adjust the 
	 * start to be outside of the metadata zone.  If the range
	 * is entirely inside the metadata zone then we can deny the
	 * request (dskFulErr).
	 */
	if (!useMetaZone && (vcb->hfs_flags & HFS_METADATA_ZONE)) {
		if (startingBlock <= vcb->hfs_metazone_end) {
			if (endingBlock > (vcb->hfs_metazone_end + 2))
				startingBlock = vcb->hfs_metazone_end + 1;
			else {
				err = dskFulErr;
				goto Exit;
			}
		}
	}

	//	Since this routine doesn't wrap around
	if (maxBlocks > (endingBlock - startingBlock)) {
		maxBlocks = endingBlock - startingBlock;
	}

	//
	//	Pre-read the first bitmap block
	//
	err = ReadBitmapBlock(vcb, startingBlock, &currCache, &blockRef);
	if (err != noErr) goto Exit;
	buffer = currCache;

	//
	//	Set up the current position within the block
	//
	{
		u_int32_t wordIndexInBlock;
		
		bitsPerBlock  = vcb->vcbVBMIOSize * kBitsPerByte;
		wordsPerBlock = vcb->vcbVBMIOSize / kBytesPerWord;

		wordIndexInBlock = (startingBlock & (bitsPerBlock-1)) / kBitsPerWord;
		buffer += wordIndexInBlock;
		wordsLeft = wordsPerBlock - wordIndexInBlock;
		currentWord = SWAP_BE32 (*buffer);
		bitMask = kHighBitInWordMask >> (startingBlock & kBitsWithinWordMask);
	}
	
	//
	//	Find the first unallocated block
	//
	block=startingBlock;
	while (block < endingBlock) {
		if ((currentWord & bitMask) == 0)
			break;

		//	Next bit
		++block;
		bitMask >>= 1;
		if (bitMask == 0) {
			//	Next word
			bitMask = kHighBitInWordMask;
			++buffer;

			if (--wordsLeft == 0) {
				//	Next block
				buffer = currCache = NULL;
				err = ReleaseBitmapBlock(vcb, blockRef, false);
				if (err != noErr) goto Exit;

				/*
				 * Skip over metadata blocks.
				 */
				if (!useMetaZone) {
					block = NextBitmapBlock(vcb, block);
				}
				if (block >= endingBlock) {
					err = dskFulErr;
					goto Exit;
				}

				err = ReadBitmapBlock(vcb, block, &currCache, &blockRef);
				if (err != noErr) goto Exit;
				buffer = currCache;

				wordsLeft = wordsPerBlock;
			}
			currentWord = SWAP_BE32 (*buffer);
		}
	}

	//	Did we get to the end of the bitmap before finding a free block?
	//	If so, then couldn't allocate anything.
	if (block >= endingBlock) {
		err = dskFulErr;
		goto Exit;
	}

	//	Return the first block in the allocated range
	*actualStartBlock = block;
	dirty = true;
	
	//	If we could get the desired number of blocks before hitting endingBlock,
	//	then adjust endingBlock so we won't keep looking.  Ideally, the comparison
	//	would be (block + maxBlocks) < endingBlock, but that could overflow.  The
	//	comparison below yields identical results, but without overflow.
	if (block < (endingBlock-maxBlocks)) {
		endingBlock = block + maxBlocks;	//	if we get this far, we've found enough
	}
	
	// XXXdbg
	if (hfsmp->jnl) {
		journal_modify_block_start(hfsmp->jnl, (struct buf *)blockRef);
	}

	//
	//	Allocate all of the consecutive blocks
	//
	while ((currentWord & bitMask) == 0) {
		//	Allocate this block
		currentWord |= bitMask;
		
		//	Move to the next block.  If no more, then exit.
		++block;
		if (block == endingBlock)
			break;

		//	Next bit
		bitMask >>= 1;
		if (bitMask == 0) {
			*buffer = SWAP_BE32 (currentWord);					//	update value in bitmap
			
			//	Next word
			bitMask = kHighBitInWordMask;
			++buffer;
			
			if (--wordsLeft == 0) {
				//	Next block
				buffer = currCache = NULL;
				err = ReleaseBitmapBlock(vcb, blockRef, true);
				if (err != noErr) goto Exit;

				/*
				 * Skip over metadata blocks.
				 */
				if (!useMetaZone) {
					u_int32_t nextBlock;

					nextBlock = NextBitmapBlock(vcb, block);
					if (nextBlock != block) {
						goto Exit;  /* allocation gap, so stop */
					}
				}

				err = ReadBitmapBlock(vcb, block, &currCache, &blockRef);
				if (err != noErr) goto Exit;
				buffer = currCache;

				// XXXdbg
				if (hfsmp->jnl) {
					journal_modify_block_start(hfsmp->jnl, (struct buf *)blockRef);
				}
				
				wordsLeft = wordsPerBlock;
			}
			
			currentWord = SWAP_BE32 (*buffer);
		}
	}
	*buffer = SWAP_BE32 (currentWord);							//	update the last change

Exit:
	if (err == noErr) {
		*actualNumBlocks = block - *actualStartBlock;

	// sanity check
	if ((*actualStartBlock + *actualNumBlocks) > vcb->allocLimit)
		panic("BlockAllocateAny: allocation overflow on \"%s\"", vcb->vcbVN);
	}
	else {
		*actualStartBlock = 0;
		*actualNumBlocks = 0;
	}
	
    if (currCache)
    	(void) ReleaseBitmapBlock(vcb, blockRef, dirty);

	return err;
}
示例#24
0
文件: hfs.c 项目: carriercomm/osx-2
static long ReadBTreeEntry(long btree, void * key, char * entry, long * dirIndex)
{
    long             extentSize;
    void             *extent;
    short            extentFile;
    char             *nodeBuf;
    BTNodeDescriptor *node;
    long             nodeSize, result = 0, entrySize = 0;
    long             curNode, index = 0, lowerBound, upperBound;
    char             *testKey, *recordData;

    // Figure out which tree is being looked at.
    if (btree == kBTreeCatalog) {
        if (gIsHFSPlus) {
            extent     = &gHFSPlus->catalogFile.extents;
            extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
        } else {
            extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
            extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
        }
        extentFile = kHFSCatalogFileID;
    } else {
        if (gIsHFSPlus) {
            extent     = &gHFSPlus->extentsFile.extents;
            extentSize = SWAP_BE64(gHFSPlus->extentsFile.logicalSize);
        } else {
            extent     = (HFSExtentDescriptor *)&gHFSMDB->drXTExtRec;
            extentSize = SWAP_BE32(gHFSMDB->drXTFlSize);
        }
        extentFile = kHFSExtentsFileID;
    }

    // Read the BTree Header if needed.
    if (gBTHeaders[btree] == 0) {
        ReadExtent(extent, extentSize, extentFile, 0, 256,
                   gBTreeHeaderBuffer + btree * 256, 0);
        gBTHeaders[btree] = (BTHeaderRec *)(gBTreeHeaderBuffer + btree * 256 +
                                            sizeof(BTNodeDescriptor));
        if ((gIsHFSPlus && btree == kBTreeCatalog) &&
            (gBTHeaders[btree]->keyCompareType == kHFSBinaryCompare)) {
          gCaseSensitive = 1;
        }
    }

    curNode  = SWAP_BE32(gBTHeaders[btree]->rootNode);
    nodeSize = SWAP_BE16(gBTHeaders[btree]->nodeSize);
    nodeBuf  = (char *)malloc(nodeSize);
    node     = (BTNodeDescriptor *)nodeBuf;

    while (1) {
        // Read the current node.
        ReadExtent(extent, extentSize, extentFile,
                   curNode * nodeSize, nodeSize, nodeBuf, 1);
    
        // Find the matching key.
        lowerBound = 0;
        upperBound = SWAP_BE16(node->numRecords) - 1;
        while (lowerBound <= upperBound) {
            index = (lowerBound + upperBound) / 2;

            GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData);

            if (gIsHFSPlus) {
                if (btree == kBTreeCatalog) {
                    result = CompareHFSPlusCatalogKeys(key, testKey);
                } else {
                    result = CompareHFSPlusExtentsKeys(key, testKey);
                }
            } else {
                if (btree == kBTreeCatalog) {
                    result = CompareHFSCatalogKeys(key, testKey);
                } else {
                    result = CompareHFSExtentsKeys(key, testKey);
                }
            }
      
            if (result < 0) upperBound = index - 1;        // search < trial
            else if (result > 0) lowerBound = index + 1;   // search > trial
            else break;                                    // search = trial
        }
    
        if (result < 0) {
            index = upperBound;
            GetBTreeRecord(index, nodeBuf, nodeSize, &testKey, &recordData);
        }
    
        // Found the closest key... Recurse on it if this is an index node.
        if (node->kind == kBTIndexNode) {
            curNode = SWAP_BE32( *((long *)recordData) );
        } else break;
    }
  
    // Return error if the file was not found.
    if (result != 0) { free(nodeBuf); return -1; }

    if (btree == kBTreeCatalog) {
        switch (SWAP_BE16(*(short *)recordData)) {
            case kHFSFolderRecord           : entrySize = 70;  break;
            case kHFSFileRecord             : entrySize = 102; break;
            case kHFSFolderThreadRecord     : entrySize = 46;  break;
            case kHFSFileThreadRecord       : entrySize = 46;  break;
            case kHFSPlusFolderRecord       : entrySize = 88;  break;
            case kHFSPlusFileRecord         : entrySize = 248; break;
            case kHFSPlusFolderThreadRecord : entrySize = 264; break;
            case kHFSPlusFileThreadRecord   : entrySize = 264; break;
        }
    } else {
        if (gIsHFSPlus) entrySize = sizeof(HFSPlusExtentRecord);
        else entrySize = sizeof(HFSExtentRecord);
    }
  
    bcopy(recordData, entry, entrySize);

    // Update dirIndex.
    if (dirIndex != 0) {
        index++;
        if (index == SWAP_BE16(node->numRecords)) {
            index = 0;
            curNode = SWAP_BE32(node->fLink);
        }
        *dirIndex = curNode * nodeSize + index;
    }
  
    free(nodeBuf);
  
    return 0;
}
示例#25
0
/*
 * hfs_swap_HFSPlusVolumeHeader
 */
void
hfs_swap_HFSPlusVolumeHeader (
    void *buf
)
{
    HFSPlusVolumeHeader *src = (HFSPlusVolumeHeader *)buf;

    src->signature			= SWAP_BE16 (src->signature);
    src->version			= SWAP_BE16 (src->version);
    src->attributes			= SWAP_BE32 (src->attributes);
    src->lastMountedVersion	= SWAP_BE32 (src->lastMountedVersion);

    src->journalInfoBlock	= SWAP_BE32 (src->journalInfoBlock);

    src->createDate			= SWAP_BE32 (src->createDate);
    src->modifyDate			= SWAP_BE32 (src->modifyDate);
    src->backupDate			= SWAP_BE32 (src->backupDate);
    src->checkedDate		= SWAP_BE32 (src->checkedDate);
    src->fileCount			= SWAP_BE32 (src->fileCount);
    src->folderCount		= SWAP_BE32 (src->folderCount);
    src->blockSize			= SWAP_BE32 (src->blockSize);
    src->totalBlocks		= SWAP_BE32 (src->totalBlocks);
    src->freeBlocks			= SWAP_BE32 (src->freeBlocks);
    src->nextAllocation		= SWAP_BE32 (src->nextAllocation);
    src->rsrcClumpSize		= SWAP_BE32 (src->rsrcClumpSize);
    src->dataClumpSize		= SWAP_BE32 (src->dataClumpSize);
    src->nextCatalogID		= SWAP_BE32 (src->nextCatalogID);
    src->writeCount			= SWAP_BE32 (src->writeCount);
    src->encodingsBitmap	= SWAP_BE64 (src->encodingsBitmap);

    /* Don't swap finderInfo */

    hfs_swap_HFSPlusForkData (&src->allocationFile);
    hfs_swap_HFSPlusForkData (&src->extentsFile);
    hfs_swap_HFSPlusForkData (&src->catalogFile);
    hfs_swap_HFSPlusForkData (&src->attributesFile);
    hfs_swap_HFSPlusForkData (&src->startupFile);
}
示例#26
0
文件: hfs.c 项目: carriercomm/osx-2
static long GetCatalogEntryInfo(void * entry, long * flags, long * time,
                                FinderInfo * finderInfo, long * infoValid)
{
    long tmpTime = 0;
    long valid = 0;

    // Get information about the file.
    
    switch ( SWAP_BE16(*(short *)entry) )
    {
        case kHFSFolderRecord           :
            *flags = kFileTypeDirectory;
            tmpTime = SWAP_BE32(((HFSCatalogFolder *)entry)->modifyDate);
            break;

        case kHFSPlusFolderRecord       :
            *flags = kFileTypeDirectory |
                     (SWAP_BE16(((HFSPlusCatalogFolder *)entry)->bsdInfo.fileMode) & kPermMask);
            if (SWAP_BE32(((HFSPlusCatalogFolder *)entry)->bsdInfo.ownerID) != 0)
                *flags |= kOwnerNotRoot;
            tmpTime = SWAP_BE32(((HFSPlusCatalogFolder *)entry)->contentModDate);
            break;

        case kHFSFileRecord             :
            *flags = kFileTypeFlat;
            tmpTime = SWAP_BE32(((HFSCatalogFile *)entry)->modifyDate);
            if (finderInfo) {
                SwapFinderInfo((FndrFileInfo *)finderInfo, &((HFSCatalogFile *)entry)->userInfo);
                valid = 1;
            }
            break;

        case kHFSPlusFileRecord         :
            *flags = kFileTypeFlat |
                     (SWAP_BE16(((HFSPlusCatalogFile *)entry)->bsdInfo.fileMode) & kPermMask);
            if (SWAP_BE32(((HFSPlusCatalogFile *)entry)->bsdInfo.ownerID) != 0)
                *flags |= kOwnerNotRoot;
            tmpTime = SWAP_BE32(((HFSPlusCatalogFile *)entry)->contentModDate);
            if (finderInfo) {
                SwapFinderInfo((FndrFileInfo *)finderInfo, &((HFSPlusCatalogFile *)entry)->userInfo);
                valid = 1;
            }
            break;

        case kHFSFileThreadRecord       :
        case kHFSPlusFileThreadRecord   :
        case kHFSFolderThreadRecord     :
        case kHFSPlusFolderThreadRecord :
            *flags = kFileTypeUnknown;
            tmpTime = 0;
            break;
    }

    if (time != 0) {
        // Convert base time from 1904 to 1970.
        *time = tmpTime - 2082844800;
    }
    if (infoValid) *infoValid = valid;

    return 0;
}
示例#27
0
static void update_status(struct svdir *s)
{
	ssize_t sz;
	int fd;
	svstatus_t status;

	/* pid */
	if (pidchanged) {
		fd = open_trunc_or_warn("supervise/pid.new");
		if (fd < 0)
			return;
		if (s->pid) {
			char spid[sizeof(int)*3 + 2];
			int size = sprintf(spid, "%u\n", (unsigned)s->pid);
			write(fd, spid, size);
		}
		close(fd);
		if (rename_or_warn("supervise/pid.new",
				s->islog ? "log/supervise/pid" : "log/supervise/pid"+4))
			return;
		pidchanged = 0;
	}

	/* stat */
	fd = open_trunc_or_warn("supervise/stat.new");
	if (fd < -1)
		return;

	{
		char stat_buf[sizeof("finish, paused, got TERM, want down\n")];
		char *p = stat_buf;
		switch (s->state) {
		case S_DOWN:
			p = stpcpy(p, "down");
			break;
		case S_RUN:
			p = stpcpy(p, "run");
			break;
		case S_FINISH:
			p = stpcpy(p, "finish");
			break;
		}
		if (s->ctrl & C_PAUSE)
			p = stpcpy(p, ", paused");
		if (s->ctrl & C_TERM)
			p = stpcpy(p, ", got TERM");
		if (s->state != S_DOWN)
			switch (s->sd_want) {
			case W_DOWN:
				p = stpcpy(p, ", want down");
				break;
			case W_EXIT:
				p = stpcpy(p, ", want exit");
				break;
			}
		*p++ = '\n';
		write(fd, stat_buf, p - stat_buf);
		close(fd);
	}

	rename_or_warn("supervise/stat.new",
		s->islog ? "log/supervise/stat" : "log/supervise/stat"+4);

	/* supervise compatibility */
	memset(&status, 0, sizeof(status));
	status.time_be64 = SWAP_BE64(s->start.tv_sec + 0x400000000000000aULL);
	status.time_nsec_be32 = SWAP_BE32(s->start.tv_nsec);
	status.pid_le32 = SWAP_LE32(s->pid);
	if (s->ctrl & C_PAUSE)
		status.paused = 1;
	if (s->sd_want == W_UP)
		status.want = 'u';
	else
		status.want = 'd';
	if (s->ctrl & C_TERM)
		status.got_term = 1;
	status.run_or_finish = s->state;
	fd = open_trunc_or_warn("supervise/status.new");
	if (fd < 0)
		return;
	sz = write(fd, &status, sizeof(status));
	close(fd);
	if (sz != sizeof(status)) {
		warn_cannot("write supervise/status.new");
		unlink("supervise/status.new");
		return;
	}
	rename_or_warn("supervise/status.new",
		s->islog ? "log/supervise/status" : "log/supervise/status"+4);
}
示例#28
0
文件: hfs.c 项目: carriercomm/osx-2
long HFSInitPartition(CICell ih)
{
    long extentSize, extentFile, nodeSize;
    void *extent;

    if (ih == gCurrentIH) {
#ifdef __i386__
        CacheInit(ih, gCacheBlockSize);
#endif
        return 0;
    }

#ifdef __i386__
    if (!gTempStr) gTempStr = (char *)malloc(4096);
    if (!gLinkTemp) gLinkTemp = (char *)malloc(64);
    if (!gBTreeHeaderBuffer) gBTreeHeaderBuffer = (char *)malloc(512);
    if (!gHFSMdbVib) {
        gHFSMdbVib = (char *)malloc(kBlockSize);
        gHFSMDB = (HFSMasterDirectoryBlock *)gHFSMdbVib;
    }
    if (!gHFSPlusHeader) {
        gHFSPlusHeader = (char *)malloc(kBlockSize);
        gHFSPlus = (HFSPlusVolumeHeader *)gHFSPlusHeader;
    }
    if (!gTempStr || !gLinkTemp || !gBTreeHeaderBuffer ||
        !gHFSMdbVib || !gHFSPlusHeader) return -1;
#endif /* __i386__ */

    gAllocationOffset = 0;
    gIsHFSPlus = 0;
    gCaseSensitive = 0;
    gBTHeaders[0] = 0;
    gBTHeaders[1] = 0;

    // Look for the HFS MDB
    Seek(ih, kMDBBaseOffset);
    Read(ih, (long)gHFSMdbVib, kBlockSize);

    if ( SWAP_BE16(gHFSMDB->drSigWord) == kHFSSigWord ) {
        gAllocationOffset = SWAP_BE16(gHFSMDB->drAlBlSt) * kBlockSize;

        // See if it is HFSPlus
        if (SWAP_BE16(gHFSMDB->drEmbedSigWord) != kHFSPlusSigWord) {
            // Normal HFS;
            gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSMDB->drAlBlkSiz);
            CacheInit(ih, gCacheBlockSize);
            gCurrentIH = ih;

            // grab the 64 bit volume ID
            bcopy(&gHFSMDB->drFndrInfo[6], &gVolID, 8);

            // Get the Catalog BTree node size.
            extent     = (HFSExtentDescriptor *)&gHFSMDB->drCTExtRec;
            extentSize = SWAP_BE32(gHFSMDB->drCTFlSize);
            extentFile = kHFSCatalogFileID;
            ReadExtent(extent, extentSize, extentFile, 0, 256,
                       gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);

            nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 + 
                                 sizeof(BTNodeDescriptor)))->nodeSize);

            // If the BTree node size is larger than the block size, reset the cache.
            if (nodeSize > gBlockSize) {
                gCacheBlockSize = nodeSize;
                CacheInit(ih, gCacheBlockSize);
            }

            return 0;
        }

        // Calculate the offset to the embeded HFSPlus volume.
        gAllocationOffset += (long long)SWAP_BE16(gHFSMDB->drEmbedExtent.startBlock) *
                                        SWAP_BE32(gHFSMDB->drAlBlkSiz);
    }

    // Look for the HFSPlus Header
    Seek(ih, gAllocationOffset + kMDBBaseOffset);
    Read(ih, (long)gHFSPlusHeader, kBlockSize);

    // Not a HFS+ or HFSX volume.
    if (SWAP_BE16(gHFSPlus->signature) != kHFSPlusSigWord &&
        SWAP_BE16(gHFSPlus->signature) != kHFSXSigWord) {
	verbose("HFS signature was not present.\n");
        gCurrentIH = 0;
	return -1;
    }

    gIsHFSPlus = 1;
    gCacheBlockSize = gBlockSize = SWAP_BE32(gHFSPlus->blockSize);
    CacheInit(ih, gCacheBlockSize);
    gCurrentIH = ih;

    // grab the 64 bit volume ID
    bcopy(&gHFSPlus->finderInfo[24], &gVolID, 8);

    // Get the Catalog BTree node size.
    extent     = &gHFSPlus->catalogFile.extents;
    extentSize = SWAP_BE64(gHFSPlus->catalogFile.logicalSize);
    extentFile = kHFSCatalogFileID;

    ReadExtent(extent, extentSize, extentFile, 0, 256,
               gBTreeHeaderBuffer + kBTreeCatalog * 256, 0);

    nodeSize = SWAP_BE16(((BTHeaderRec *)(gBTreeHeaderBuffer + kBTreeCatalog * 256 +
                         sizeof(BTNodeDescriptor)))->nodeSize);

    // If the BTree node size is larger than the block size, reset the cache.
    if (nodeSize > gBlockSize) {
        gCacheBlockSize = nodeSize;
        CacheInit(ih, gCacheBlockSize);
    }

    return 0;
}
示例#29
0
/*
 * hfs_swap_HFSMasterDirectoryBlock
 *
 *  Specially modified to swap parts of the finder info
 */
void
hfs_swap_HFSMasterDirectoryBlock (
    void *buf
)
{
    HFSMasterDirectoryBlock *src = (HFSMasterDirectoryBlock *)buf;

    src->drSigWord		= SWAP_BE16 (src->drSigWord);
    src->drCrDate		= SWAP_BE32 (src->drCrDate);
    src->drLsMod		= SWAP_BE32 (src->drLsMod);
    src->drAtrb			= SWAP_BE16 (src->drAtrb);
    src->drNmFls		= SWAP_BE16 (src->drNmFls);
    src->drVBMSt		= SWAP_BE16 (src->drVBMSt);
    src->drAllocPtr		= SWAP_BE16 (src->drAllocPtr);
    src->drNmAlBlks		= SWAP_BE16 (src->drNmAlBlks);
    src->drAlBlkSiz		= SWAP_BE32 (src->drAlBlkSiz);
    src->drClpSiz		= SWAP_BE32 (src->drClpSiz);
    src->drAlBlSt		= SWAP_BE16 (src->drAlBlSt);
    src->drNxtCNID		= SWAP_BE32 (src->drNxtCNID);
    src->drFreeBks		= SWAP_BE16 (src->drFreeBks);

    /* Don't swap drVN */

    src->drVolBkUp		= SWAP_BE32 (src->drVolBkUp);
    src->drVSeqNum		= SWAP_BE16 (src->drVSeqNum);
    src->drWrCnt		= SWAP_BE32 (src->drWrCnt);
    src->drXTClpSiz		= SWAP_BE32 (src->drXTClpSiz);
    src->drCTClpSiz		= SWAP_BE32 (src->drCTClpSiz);
    src->drNmRtDirs		= SWAP_BE16 (src->drNmRtDirs);
    src->drFilCnt		= SWAP_BE32 (src->drFilCnt);
    src->drDirCnt		= SWAP_BE32 (src->drDirCnt);

    /* Swap just the 'blessed folder' in drFndrInfo */
    src->drFndrInfo[0]	= SWAP_BE32 (src->drFndrInfo[0]);

    src->drEmbedSigWord	= SWAP_BE16 (src->drEmbedSigWord);
	src->drEmbedExtent.startBlock = SWAP_BE16 (src->drEmbedExtent.startBlock);
	src->drEmbedExtent.blockCount = SWAP_BE16 (src->drEmbedExtent.blockCount);

    src->drXTFlSize		= SWAP_BE32 (src->drXTFlSize);
	src->drXTExtRec[0].startBlock = SWAP_BE16 (src->drXTExtRec[0].startBlock);
	src->drXTExtRec[0].blockCount = SWAP_BE16 (src->drXTExtRec[0].blockCount);
	src->drXTExtRec[1].startBlock = SWAP_BE16 (src->drXTExtRec[1].startBlock);
	src->drXTExtRec[1].blockCount = SWAP_BE16 (src->drXTExtRec[1].blockCount);
	src->drXTExtRec[2].startBlock = SWAP_BE16 (src->drXTExtRec[2].startBlock);
	src->drXTExtRec[2].blockCount = SWAP_BE16 (src->drXTExtRec[2].blockCount);

    src->drCTFlSize		= SWAP_BE32 (src->drCTFlSize);
	src->drCTExtRec[0].startBlock = SWAP_BE16 (src->drCTExtRec[0].startBlock);
	src->drCTExtRec[0].blockCount = SWAP_BE16 (src->drCTExtRec[0].blockCount);
	src->drCTExtRec[1].startBlock = SWAP_BE16 (src->drCTExtRec[1].startBlock);
	src->drCTExtRec[1].blockCount = SWAP_BE16 (src->drCTExtRec[1].blockCount);
	src->drCTExtRec[2].startBlock = SWAP_BE16 (src->drCTExtRec[2].startBlock);
	src->drCTExtRec[2].blockCount = SWAP_BE16 (src->drCTExtRec[2].blockCount);
}
示例#30
0
void nbd_client_main(void)
{
  int sock = -1, nbd, flags;
  unsigned long timeout = 0;
  char *host=toys.optargs[0], *port=toys.optargs[1], *device=toys.optargs[2];
  uint64_t devsize;

  // Repeat until spanked

  nbd = xopen(device, O_RDWR);
  for (;;) {
    int temp;

    // Find and connect to server

    sock = xconnect(xgetaddrinfo(host, port, AF_UNSPEC, SOCK_STREAM, 0, 0));
    temp = 1;
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &temp, sizeof(int));

    // Read login data

    xreadall(sock, toybuf, 152);
    if (memcmp(toybuf, "NBDMAGIC\x00\x00\x42\x02\x81\x86\x12\x53", 16))
      error_exit("bad login %s:%s", host, port);
    devsize = SWAP_BE64(*(uint64_t *)(toybuf+16));
    flags = SWAP_BE32(*(int *)(toybuf+24));

    // Set 4k block size.  Everything uses that these days.
    ioctl(nbd, NBD_SET_BLKSIZE, 4096);
    ioctl(nbd, NBD_SET_SIZE_BLOCKS, devsize/4096);
    ioctl(nbd, NBD_CLEAR_SOCK);

    // If the sucker was exported read only, respect that locally.
    temp = (flags & 2) ? 1 : 0;
    xioctl(nbd, BLKROSET, &temp);

    if (timeout && ioctl(nbd, NBD_SET_TIMEOUT, timeout)<0) break;
    if (ioctl(nbd, NBD_SET_SOCK, sock) < 0) break;

    if (toys.optflags & FLAG_s) mlockall(MCL_CURRENT|MCL_FUTURE);

    // Open the device to force reread of the partition table.
    if ((toys.optflags & FLAG_n) || !xfork()) {
      char *s = strrchr(device, '/');
      int i;

      sprintf(toybuf, "/sys/block/%.32s/pid", s ? s+1 : device);
      // Is it up yet? (Give it 10 seconds.)
      for (i=0; i<100; i++) {
        temp = open(toybuf, O_RDONLY);
        if (temp == -1) msleep(100);
        else {
          close(temp);
          break;
        }
      }
      close(open(device, O_RDONLY));
      if (!(toys.optflags & FLAG_n)) exit(0);
    }

    // Daemonize here.

    if (daemon(0,0)) perror_exit("daemonize");

    // Process NBD requests until further notice.

    if (ioctl(nbd, NBD_DO_IT)>=0 || errno==EBADR) break;
    close(sock);
  }

  // Flush queue and exit.
  ioctl(nbd, NBD_CLEAR_QUE);
  ioctl(nbd, NBD_CLEAR_SOCK);
  if (CFG_TOYBOX_FREE) close(nbd);
}