Пример #1
0
uint32 File::GetDeviceSectorSize () const
{
    if (Path.IsDevice())
    {
#ifdef TC_LINUX
        int blockSize;
        throw_sys_sub_if (ioctl (FileHandle, BLKSSZGET, &blockSize) == -1, wstring (Path));
        return blockSize;

#elif defined (TC_MACOSX)
        uint32 blockSize;
        throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
        return blockSize;

#elif defined (TC_FREEBSD)
        u_int sectorSize;
        throw_sys_sub_if (ioctl (FileHandle, DIOCGSECTORSIZE, &sectorSize) == -1, wstring (Path));
        return (uint32) sectorSize;

#elif defined (TC_SOLARIS)
        struct dk_minfo mediaInfo;
        throw_sys_sub_if (ioctl (FileHandle, DKIOCGMEDIAINFO, &mediaInfo) == -1, wstring (Path));
        return mediaInfo.dki_lbsize;

#else
#	error GetDeviceSectorSize()
#endif
    }
    else
        throw ParameterIncorrect (SRC_POS);
}
Пример #2
0
uint64 File::Length () const
{
    if_debug (ValidateState());

    // BSD does not support seeking to the end of a device
#ifdef TC_BSD
    if (Path.IsBlockDevice() || Path.IsCharacterDevice())
    {
#	ifdef TC_MACOSX
        uint32 blockSize;
        uint64 blockCount;
        throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKSIZE, &blockSize) == -1, wstring (Path));
        throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBLOCKCOUNT, &blockCount) == -1, wstring (Path));
        return blockCount * blockSize;
#	else
        uint64 mediaSize;
        throw_sys_sub_if (ioctl (FileHandle, DIOCGMEDIASIZE, &mediaSize) == -1, wstring (Path));
        return mediaSize;
#	endif
    }
#endif
    off_t current = lseek (FileHandle, 0, SEEK_CUR);
    throw_sys_sub_if (current == -1, wstring (Path));
    SeekEnd (0);
    uint64 length = lseek (FileHandle, 0, SEEK_CUR);
    SeekAt (current);
    return length;
}
Пример #3
0
uint64 File::GetPartitionDeviceStartOffset () const
{
#ifdef TC_LINUX

    // HDIO_GETGEO ioctl is limited by the size of long
    TextReader tr ("/sys/block/" + string (Path.ToHostDriveOfPartition().ToBaseName()) + "/" + string (Path.ToBaseName()) + "/start");

    string line;
    tr.ReadLine (line);
    return StringConverter::ToUInt64 (line) * GetDeviceSectorSize();

#elif defined (TC_MACOSX)

#ifndef DKIOCGETBASE
#	define DKIOCGETBASE _IOR('d', 73, uint64)
#endif
    uint64 offset;
    throw_sys_sub_if (ioctl (FileHandle, DKIOCGETBASE, &offset) == -1, wstring (Path));
    return offset;

#elif defined (TC_SOLARIS)

    struct extpart_info partInfo;
    throw_sys_sub_if (ioctl (FileHandle, DKIOCEXTPARTINFO, &partInfo) == -1, wstring (Path));
    return partInfo.p_start * GetDeviceSectorSize();

#else
    throw NotImplemented (SRC_POS);
#endif
}
Пример #4
0
	void File::Copy (const FilePath &sourcePath, const FilePath &destinationPath, bool preserveTimestamps)
	{
		File source;
		source.Open (sourcePath);

		File destination;
		destination.Open (destinationPath, CreateWrite);

		SecureBuffer buffer (OptimalReadSize);
		uint64 len;

		while ((len = source.Read (buffer)) > 0)
		{
			destination.Write (buffer, static_cast <size_t> (len));
		}

		if (preserveTimestamps)
		{
			destination.Flush();
#ifndef TC_WINDOWS
			struct stat statData;
			throw_sys_sub_if (stat (string (sourcePath).c_str(), &statData) == -1, wstring (sourcePath));

			struct utimbuf u;
			u.actime = statData.st_atime;
			u.modtime = statData.st_mtime;
			throw_sys_sub_if (utime (string (destinationPath).c_str(), &u) == -1, wstring (destinationPath));
#endif
		}
	}
Пример #5
0
void File::Close ()
{
    if_debug (ValidateState());

    if (!SharedHandle)
    {
        close (FileHandle);
        FileIsOpen = false;

        if ((mFileOpenFlags & File::PreserveTimestamps) && Path.IsFile())
        {
            struct utimbuf u;
            u.actime = AccTime;
            u.modtime = ModTime;

            try
            {
                throw_sys_sub_if (utime (string (Path).c_str(), &u) == -1, wstring (Path));
            }
            catch (...) // Suppress errors to allow using read-only files
            {
#ifdef DEBUG
                throw;
#endif
            }
        }
    }
}
Пример #6
0
	MountedFilesystemList CoreSolaris::GetMountedFilesystems (const DevicePath &devicePath, const DirectoryPath &mountPoint) const
	{
		MountedFilesystemList mountedFilesystems;

		FILE *mtab = fopen ("/etc/mnttab", "r");
		throw_sys_sub_if (!mtab, "/etc/mnttab");
		finally_do_arg (FILE *, mtab, { fclose (finally_arg); });
Пример #7
0
void File::WriteAt (const ConstBufferPtr &buffer, uint64 position) const
{
    if_debug (ValidateState());

#ifdef TC_TRACE_FILE_OPERATIONS
    TraceFileOperation (FileHandle, Path, true, buffer.Size(), position);
#endif
    throw_sys_sub_if (pwrite (FileHandle, buffer, buffer.Size(), position) != (ssize_t) buffer.Size(), wstring (Path));
}
Пример #8
0
uint64 File::ReadAt (const BufferPtr &buffer, uint64 position) const
{
    if_debug (ValidateState());

#ifdef TC_TRACE_FILE_OPERATIONS
    TraceFileOperation (FileHandle, Path, false, buffer.Size(), position);
#endif
    ssize_t bytesRead = pread (FileHandle, buffer, buffer.Size(), position);
    throw_sys_sub_if (bytesRead == -1, wstring (Path));

    return bytesRead;
}
Пример #9
0
void File::SeekEnd (int offset) const
{
    if_debug (ValidateState());

    // BSD does not support seeking to the end of a device
#ifdef TC_BSD
    if (Path.IsBlockDevice() || Path.IsCharacterDevice())
    {
        SeekAt (Length() + offset);
        return;
    }
#endif

    throw_sys_sub_if (lseek (FileHandle, offset, SEEK_END) == -1, wstring (Path));
}
Пример #10
0
	FilesystemPathType::Enum FilesystemPath::GetType () const
	{
		// Strip trailing directory separator
		wstring path = Path;
		size_t pos = path.find_last_not_of (L'/');
		if (path.size() > 2 && pos != path.size() - 1)
			path = path.substr (0, pos + 1);

		struct stat statData;
		throw_sys_sub_if (stat (StringConverter::ToSingle (path).c_str(), &statData) != 0, Path);
		
		if (S_ISREG (statData.st_mode)) return FilesystemPathType::File;
		if (S_ISDIR (statData.st_mode)) return FilesystemPathType::Directory;
		if (S_ISCHR (statData.st_mode)) return FilesystemPathType::CharacterDevice;
		if (S_ISBLK (statData.st_mode)) return FilesystemPathType::BlockDevice;
		if (S_ISLNK (statData.st_mode)) return FilesystemPathType::SymbolickLink;

		return FilesystemPathType::Unknown;
	}
Пример #11
0
	void CoreService::ProcessElevatedRequests ()
	{
		int pid = fork();
		throw_sys_if (pid == -1);
		if (pid == 0)
		{
			try
			{
				int f = open ("/dev/null", 0);
				throw_sys_sub_if (f == -1, "/dev/null");
				throw_sys_if (dup2 (f, STDERR_FILENO) == -1);

				// Wait for sync code
				while (true)
				{
					byte b;
					throw_sys_if (read (STDIN_FILENO, &b, 1) != 1);
					if (b != 0x00)
						continue;
					
					throw_sys_if (read (STDIN_FILENO, &b, 1) != 1);
					if (b != 0x11)
						continue;
					
					throw_sys_if (read (STDIN_FILENO, &b, 1) != 1);
					if (b == 0x22)
						break;
				}

				ElevatedPrivileges = true;
				ProcessRequests (STDIN_FILENO, STDOUT_FILENO);
				_exit (0);
			}
			catch (exception &e)
			{
#ifdef DEBUG
				SystemLog::WriteException (e);
#endif
			}
			catch (...)	{ }
			_exit (1);
		}
	}
Пример #12
0
	FilePathList Directory::GetFilePaths (const DirectoryPath &path, bool regularFilesOnly)
	{
		DIR *dir = opendir (string (path).c_str());
		throw_sys_sub_if (!dir, wstring (path));
		finally_do_arg (DIR*, dir, { closedir (finally_arg); });
Пример #13
0
	shared_ptr <VolumeInfo> CoreUnix::MountVolume (MountOptions &options)
	{
		CoalesceSlotNumberAndMountPoint (options);

		if (IsVolumeMounted (*options.Path))
			throw VolumeAlreadyMounted (SRC_POS);

		Cipher::EnableHwSupport (!options.NoHardwareCrypto);

		shared_ptr <Volume> volume;

		while (true)
		{
			try
			{
				volume = OpenVolume (
					options.Path,
					options.PreserveTimestamps,
					options.Password,
					options.Keyfiles,
					options.Protection,
					options.ProtectionPassword,
					options.ProtectionKeyfiles,
					options.SharedAccessAllowed,
					VolumeType::Unknown,
					options.UseBackupHeaders,
					options.PartitionInSystemEncryptionScope
					);

				options.Password.reset();
			}
			catch (SystemException &e)
			{
				if (options.Protection != VolumeProtection::ReadOnly
					&& (e.GetErrorCode() == EROFS || e.GetErrorCode() == EACCES || e.GetErrorCode() == EPERM))
				{
					// Read-only filesystem
					options.Protection = VolumeProtection::ReadOnly;
					continue;
				}

				throw;
			}

			break;
		}

		if (options.Path->IsDevice())
		{
			if (volume->GetFile()->GetDeviceSectorSize() != volume->GetSectorSize())
				throw ParameterIncorrect (SRC_POS);

#if defined (TC_LINUX)
			if (volume->GetSectorSize() != TC_SECTOR_SIZE_LEGACY)
			{
				if (options.Protection == VolumeProtection::HiddenVolumeReadOnly)
					throw UnsupportedSectorSizeHiddenVolumeProtection();

				if (options.NoKernelCrypto)
					throw UnsupportedSectorSizeNoKernelCrypto();
			}
#endif
		}

		// Find a free mount point for FUSE service
		MountedFilesystemList mountedFilesystems = GetMountedFilesystems ();
		string fuseMountPoint;
		for (int i = 1; true; i++)
		{
			stringstream path;
			path << GetTempDirectory() << "/" << GetFuseMountDirPrefix() << i;
			FilesystemPath fsPath (path.str());

			bool inUse = false;

			foreach_ref (const MountedFilesystem &mf, mountedFilesystems)
			{
				if (mf.MountPoint == path.str())
				{
					inUse = true;
					break;
				}
			}

			if (!inUse)
			{
				try
				{
					if (fsPath.IsDirectory())
						fsPath.Delete();

					throw_sys_sub_if (mkdir (path.str().c_str(), S_IRUSR | S_IXUSR) == -1, path.str());

					fuseMountPoint = fsPath;
					break;
				}
				catch (...)
				{
					if (i > 255)
						throw TemporaryDirectoryFailure (SRC_POS, StringConverter::ToWide (path.str()));
				}
			}
		}

		try
		{
			FuseService::Mount (volume, options.SlotNumber, fuseMountPoint);
		}
		catch (...)
		{
			try
			{
				DirectoryPath (fuseMountPoint).Delete();
			}
			catch (...) { }
			throw;
		}

		try
		{
			// Create a mount directory if a default path has been specified
			bool mountDirCreated = false;
			string mountPoint;
			if (!options.NoFilesystem && options.MountPoint)
			{
				mountPoint = *options.MountPoint;

#ifndef TC_MACOSX
				if (mountPoint.find (GetDefaultMountPointPrefix()) == 0 && !options.MountPoint->IsDirectory())
				{
					Directory::Create (*options.MountPoint);
					try
					{
						throw_sys_sub_if (chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()) == -1, mountPoint);
					} catch (ParameterIncorrect&) { }

					mountDirCreated = true;
				}
#endif
			}

			try
			{
				try
				{
					MountVolumeNative (volume, options, fuseMountPoint);
				}
				catch (NotApplicable&)
				{
					MountAuxVolumeImage (fuseMountPoint, options);
				}
			}
			catch (...)
			{
				if (mountDirCreated)
					remove (mountPoint.c_str());
				throw;
			}
		}
		catch (...)
		{
			try
			{
				VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path);
				if (mountedVolumes.size() > 0)
				{
					shared_ptr <VolumeInfo> mountedVolume (mountedVolumes.front());
					DismountVolume (mountedVolume);
				}
			}
			catch (...) { }
			throw;
		}

		VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path);
		if (mountedVolumes.size() != 1)
			throw ParameterIncorrect (SRC_POS);

		VolumeEventArgs eventArgs (mountedVolumes.front());
		VolumeMountedEvent.Raise (eventArgs);

		return mountedVolumes.front();
	}
Пример #14
0
	void FilesystemPath::Delete () const
	{
		throw_sys_sub_if (remove (string (*this).c_str()) == -1, Path);
	}
Пример #15
0
void File::Open (const FilePath &path, FileOpenMode mode, FileShareMode shareMode, FileOpenFlags flags)
{
#ifdef TC_LINUX
    int sysFlags = O_LARGEFILE;
#else
    int sysFlags = 0;
#endif

    switch (mode)
    {
    case CreateReadWrite:
        sysFlags |= O_CREAT | O_TRUNC | O_RDWR;
        break;

    case CreateWrite:
        sysFlags |= O_CREAT | O_TRUNC | O_WRONLY;
        break;

    case OpenRead:
        sysFlags |= O_RDONLY;
        break;

    case OpenWrite:
        sysFlags |= O_WRONLY;
        break;

    case OpenReadWrite:
        sysFlags |= O_RDWR;
        break;

    default:
        throw ParameterIncorrect (SRC_POS);
    }

    if ((flags & File::PreserveTimestamps) && path.IsFile())
    {
        struct stat statData;
        throw_sys_sub_if (stat (string (path).c_str(), &statData) == -1, wstring (path));
        AccTime = statData.st_atime;
        ModTime = statData.st_mtime;
    }

    FileHandle = open (string (path).c_str(), sysFlags, S_IRUSR | S_IWUSR);
    throw_sys_sub_if (FileHandle == -1, wstring (path));

#if 0 // File locking is disabled to avoid remote filesystem locking issues
    try
    {
        struct flock fl;
        memset (&fl, 0, sizeof (fl));
        fl.l_whence = SEEK_SET;
        fl.l_start = 0;
        fl.l_len = 0;

        switch (shareMode)
        {
        case ShareNone:
            fl.l_type = F_WRLCK;
            if (fcntl (FileHandle, F_SETLK, &fl) == -1)
                throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path));
            break;

        case ShareRead:
            fl.l_type = F_RDLCK;
            if (fcntl (FileHandle, F_SETLK, &fl) == -1)
                throw_sys_sub_if (errno == EAGAIN || errno == EACCES, wstring (path));
            break;

        case ShareReadWrite:
            fl.l_type = (mode == OpenRead ? F_RDLCK : F_WRLCK);
            if (fcntl (FileHandle, F_GETLK, &fl) != -1 && fl.l_type != F_UNLCK)
            {
                errno = EAGAIN;
                throw SystemException (SRC_POS, wstring (path));
            }
            break;

        case ShareReadWriteIgnoreLock:
            break;

        default:
            throw ParameterIncorrect (SRC_POS);
        }
    }
    catch (...)
    {
        close (FileHandle);
        throw;
    }
#endif // 0

    Path = path;
    mFileOpenFlags = flags;
    FileIsOpen = true;
}
Пример #16
0
void File::Flush () const
{
    if_debug (ValidateState());
    throw_sys_sub_if (fsync (FileHandle) != 0, wstring (Path));
}
Пример #17
0
void File::SeekAt (uint64 position) const
{
    if_debug (ValidateState());
    throw_sys_sub_if (lseek (FileHandle, position, SEEK_SET) == -1, wstring (Path));
}