コード例 #1
0
ファイル: FileManager.cpp プロジェクト: 010001111/darling
OSErr PBCreateFileUnicodeSync(FSRefParam* paramBlock)
{
	std::string path;
	
	if (!FSRefParamMakePath(paramBlock, path))
		return fnfErr;
	if (open(path.c_str(), O_CREAT|O_EXCL, 0666) == -1)
		return makeOSStatus(errno);
	
	if (paramBlock->newRef)
		FSPathMakeRef((uint8_t*) path.c_str(), paramBlock->newRef, nullptr);
	
	return noErr;
}
コード例 #2
0
ファイル: FileManager.cpp プロジェクト: 010001111/darling
OSErr PBCreateDirectoryUnicodeSync(FSRefParam* paramBlock)
{
	std::string path;
	
	if (!FSRefParamMakePath(paramBlock, path))
		return fnfErr;
	if (mkdir(path.c_str(), 0777) == -1)
		return makeOSStatus(errno);
	
	if (paramBlock->newRef)
		FSPathMakeRef((uint8_t*) path.c_str(), paramBlock->newRef, nullptr);
	
	return noErr;
}
コード例 #3
0
OSStatus FSPathMakeRefWithOptions(const uint8_t* path, long options, FSRef* fsref, Boolean* isDirectory)
{
	if (!path || !fsref)
		return paramErr;

	std::string fullPath;
	char* rpath;
	
	if (options & kFSPathMakeRefDoNotFollowLeafSymlink)
		rpath = realpath_ns(reinterpret_cast<const char*>(path));
	else
		rpath = realpath(reinterpret_cast<const char*>(path), nullptr);

	if (!rpath)
		return fnfErr;
	if (std::count(rpath, rpath+strlen(rpath), '/') > FSRef_MAX_DEPTH)
	{
		free(rpath);
		return unimpErr;
	}

	fullPath = rpath;
	free(rpath);

	memset(fsref, 0, sizeof(*fsref));

	if (fullPath == "/")
	{
		if (isDirectory)
			*isDirectory = true;
		return noErr;
	}

	std::vector<std::string> components = string_explode(fullPath, '/', false);
	std::string position = "/";
	size_t pos;

	for (size_t pos = 0; pos < components.size(); pos++)
	{
		bool found = false;
		struct dirent* ent;

		DIR* dir = opendir(position.c_str());
		if (!dir)
			return makeOSStatus(errno);

		while ((ent = readdir(dir)))
		{
			if (components[pos] == ent->d_name)
			{
				found = true;
				fsref->inodes[pos] = ent->d_ino;

				if (pos+1 == components.size() && isDirectory != nullptr)
					*isDirectory = ent->d_type == DT_DIR;
				break;
			}
		}

		closedir(dir);

		if (!found)
			return fnfErr;

		if (!string_endsWith(position, "/"))
			position += '/';
		position += components[pos];

		pos++;
	}

	return noErr; 
}
コード例 #4
0
OSStatus FSGetCatalogInfo(const FSRef* ref, uint32_t infoBits, FSCatalogInfo* infoOut, HFSUniStr255* nameOut, FSSpecPtr fsspec, FSRef* parentDir)
{
	std::string path;

	if (!FSRefMakePath(ref, path))
		return fnfErr;

	if (nameOut)
	{
		iconv_t ic = iconv_open("UTF-16", "UTF-8");
		size_t s;
		const char* inbuf = path.c_str();
		char* outbuf = reinterpret_cast<char*>(nameOut->unicode);
		size_t inbytesleft = path.size(), outbytesleft = sizeof(nameOut->unicode);

		if (ic == iconv_t(-1))
			return -1;

		memset(nameOut->unicode, 0, outbytesleft);
		s = iconv(ic, (char**) &inbuf, &inbytesleft, &outbuf, &outbytesleft);

		iconv_close(ic);
		if (s == size_t(-1))
			return -1;
	}

	if (parentDir)
	{
		memcpy(parentDir, ref, sizeof(FSRef));
		ino_t* last = std::find(parentDir->inodes, parentDir->inodes+FSRef_MAX_DEPTH, 0);

		if (last != parentDir->inodes)
			*(last-1) = 0;
	}

	if (infoOut && infoBits != kFSCatInfoNone)
	{
		struct stat st;

		memset(infoOut, 0, sizeof(*infoOut));

		if (::stat(path.c_str(), &st) != 0)
			return makeOSStatus(errno);

		if (infoBits & kFSCatInfoNodeFlags)
		{
			if (S_ISDIR(st.st_mode))
				infoOut->nodeFlags = 4;
		}
	
		if (infoBits & (kFSCatInfoParentDirID|kFSCatInfoNodeID))
		{
			if (infoBits & kFSCatInfoNodeID)
				infoOut->nodeID = ref->inodes[0];
			for (int i = FSRef_MAX_DEPTH-1; i > 0; i--)
			{
				if (ref->inodes[i] == 0)
					continue;
				
				if (infoBits & kFSCatInfoParentDirID)
					infoOut->parentDirID = ref->inodes[i-1];
				if (infoBits & kFSCatInfoNodeID)
					infoOut->nodeID = ref->inodes[i];
			}
		}

		if (infoBits & kFSCatInfoDataSizes)
		{
			infoOut->dataLogicalSize = st.st_size;
			infoOut->dataPhysicalSize = st.st_blocks*512;
		}
		
		int uaccess;
		
		if (st.st_uid == getuid())
			uaccess = st.st_mode & 0700;
		else if (hasgid(st.st_gid))
			uaccess = st.st_mode & 070;
		else
			uaccess = st.st_mode & 07;

		if (infoBits & kFSCatInfoPermissions)
		{
			const uid_t uid = getuid();

			infoOut->fsPermissionInfo.userID = st.st_uid;
			infoOut->fsPermissionInfo.groupID = st.st_gid;
			infoOut->fsPermissionInfo.mode = st.st_mode & 07777;
			infoOut->fsPermissionInfo.userAccess = uaccess;
		}

		if (infoBits & kFSCatInfoUserPrivs)
		{
			if (!(uaccess & 2))
				infoOut->userPrivileges |= 0x4; // kioACUserNoMakeChangesMask
			if (getuid() != st.st_uid)
				infoOut->userPrivileges |= 0x80; // kioACUserNotOwnerMask
		}
		if (infoBits & kFSCatInfoCreateDate)
			infoOut->createDate = Darling::time_tToUTC(st.st_ctime);
		if (infoBits & kFSCatInfoContentMod)
			infoOut->attributeModDate = infoOut->contentModDate = Darling::time_tToUTC(st.st_mtime);
		if (infoBits & kFSCatInfoAccessDate)
			infoOut->accessDate = Darling::time_tToUTC(st.st_atime);
	}

	return noErr;
}
コード例 #5
0
ファイル: LaunchServices.cpp プロジェクト: holylw2010/darling
OSStatus LSOpenApplication(const LSApplicationParameters *appParams, ProcessSerialNumber *outPSN)
{
	if (!appParams)
		return paramErr;

	std::string exePath;
	std::vector<char*> argv;
	std::unique_ptr<std::vector<char*>> envp;
	int pipefds[2];
	pid_t pid;
	OSStatus rv = noErr;

	if (!FSRefMakePath(appParams->application, exePath))
		return fnfErr;

	if (appParams->argv != nullptr)
	{
		CFIndex count = CFArrayGetCount(appParams->argv);

		for (CFIndex i = 0; i < count; i++)
		{
			CFStringRef ref = (CFStringRef) CFArrayGetValueAtIndex(appParams->argv, i);
			if (CFGetTypeID(ref) != CFStringGetTypeID())
				return paramErr;

			argv.push_back((char*) CFStringGetCStringPtr((CFStringRef) CFArrayGetValueAtIndex(appParams->argv, i), kCFStringEncodingUTF8));
		}
		argv.push_back(nullptr);
	}
	else
	{
		argv.push_back((char*) exePath.c_str());
		argv.push_back(nullptr);
	}

	if (appParams->environment != nullptr)
	{
		CFIndex count = CFDictionaryGetCount(appParams->environment);
		envp.reset(new std::vector<char*>);
		
		CFDictionaryApplyFunction(appParams->environment, [](const void* key, const void* value, void* context) {
					CFStringRef skey = (CFStringRef) key;
					CFStringRef svalue = (CFStringRef) value;
					std::vector<const char*>* envp = (std::vector<const char*>*) context;

					if (CFGetTypeID(skey) == CFStringGetTypeID() && CFGetTypeID(svalue) == CFStringGetTypeID())
					{
						char* str = new char[CFStringGetLength(skey) + CFStringGetLength(svalue) + 1];

						strcpy(str, CFStringGetCStringPtr(skey, kCFStringEncodingUTF8));
						strcat(str, "=");
						strcat(str, CFStringGetCStringPtr(svalue, kCFStringEncodingUTF8));

						envp->push_back(str);
					}
				}, envp.get());
	}

	// https://stackoverflow.com/questions/1584956/how-to-handle-execvp-errors-after-fork
	
	if (pipe(pipefds))
	{
		if (envp)
			std::for_each(envp->begin(), envp->end(), [](char* p) { delete [] p; });

		return makeOSStatus(errno);
	}

	fcntl(pipefds[1], F_SETFD, fcntl(pipefds[1], F_GETFD) | FD_CLOEXEC);

	switch (pid = fork())
	{
		case -1:
			rv = makeOSStatus(errno);
			break;
		case 0:
			close(pipefds[0]);
			execvpe(exePath.c_str(), &argv[0], envp ? &(*envp)[0] : nullptr);
			write(pipefds[1], &errno, sizeof(int));
			_exit(1);
			break;
		default:
		{
			int err, count;
			close(pipefds[1]);

			while ((count = read(pipefds[0], &err, sizeof(errno))) == -1)
			{
				if (errno != EAGAIN && errno != EINTR)
					break;
			}

			if (count > 0)
				rv = makeOSStatus(err);
			close(pipefds[0]);
		}
	}
	
	if (envp)
		std::for_each(envp->begin(), envp->end(), [](char* p) { delete [] p; });

	return rv;
}
コード例 #6
0
ファイル: FileManager.cpp プロジェクト: 010001111/darling
OSStatus FSGetCatalogInfo(const FSRef* ref, uint32_t infoBits, FSCatalogInfo* infoOut, HFSUniStr255* nameOut, FSSpecPtr fsspec, FSRef* parentDir)
{
	std::string path;

	if (!FSRefMakePath(ref, path))
		return fnfErr;

	if (nameOut)
	{
		CFStringRef cfstr = CFStringCreateWithCString(NULL, path.c_str(), kCFStringEncodingUTF8);
		nameOut->length = std::min<size_t>(path.length(), 255);
		CFStringGetCharacters(cfstr, CFRangeMake(0, nameOut->length), nameOut->unicode);
		CFRelease(cfstr);
	}

	if (parentDir)
	{
		memcpy(parentDir, ref, sizeof(FSRef));
		ino_t* last = std::find(parentDir->inodes, parentDir->inodes+FSRef_MAX_DEPTH, 0);

		if (last != parentDir->inodes)
			*(last-1) = 0;
	}

	if (infoOut && infoBits != kFSCatInfoNone)
	{
		struct stat st;

		memset(infoOut, 0, sizeof(*infoOut));

		if (::stat(path.c_str(), &st) != 0)
			return makeOSStatus(errno);

		if (infoBits & kFSCatInfoNodeFlags)
		{
			if (S_ISDIR(st.st_mode))
				infoOut->nodeFlags = 4;
		}
	
		if (infoBits & (kFSCatInfoParentDirID|kFSCatInfoNodeID))
		{
			if (infoBits & kFSCatInfoNodeID)
				infoOut->nodeID = ref->inodes[0];
			for (int i = FSRef_MAX_DEPTH-1; i > 0; i--)
			{
				if (ref->inodes[i] == 0)
					continue;
				
				if (infoBits & kFSCatInfoParentDirID)
					infoOut->parentDirID = ref->inodes[i-1];
				if (infoBits & kFSCatInfoNodeID)
					infoOut->nodeID = ref->inodes[i];
			}
		}

		if (infoBits & kFSCatInfoDataSizes)
		{
			infoOut->dataLogicalSize = st.st_size;
			infoOut->dataPhysicalSize = st.st_blocks*512;
		}
		
		int uaccess;
		
		if (st.st_uid == getuid())
			uaccess = st.st_mode & 0700;
		else if (hasgid(st.st_gid))
			uaccess = st.st_mode & 070;
		else
			uaccess = st.st_mode & 07;

		if (infoBits & kFSCatInfoPermissions)
		{
			const uid_t uid = getuid();

			infoOut->fsPermissionInfo.userID = st.st_uid;
			infoOut->fsPermissionInfo.groupID = st.st_gid;
			infoOut->fsPermissionInfo.mode = st.st_mode & 07777;
			infoOut->fsPermissionInfo.userAccess = uaccess;
		}

		if (infoBits & kFSCatInfoUserPrivs)
		{
			if (!(uaccess & 2))
				infoOut->userPrivileges |= 0x4; // kioACUserNoMakeChangesMask
			if (getuid() != st.st_uid)
				infoOut->userPrivileges |= 0x80; // kioACUserNotOwnerMask
		}
		if (infoBits & kFSCatInfoCreateDate)
			infoOut->createDate = Darling::time_tToUTC(st.st_ctime);
		if (infoBits & kFSCatInfoContentMod)
			infoOut->attributeModDate = infoOut->contentModDate = Darling::time_tToUTC(st.st_mtime);
		if (infoBits & kFSCatInfoAccessDate)
			infoOut->accessDate = Darling::time_tToUTC(st.st_atime);
	}

	return noErr;
}