Exemple #1
0
static uint32
disk_write(IRP * irp)
{
	FILE_INFO * finfo;
	ssize_t r;
	uint32 len;

	LLOGLN(10, ("disk_write: id=%d len=%d off=%lld", irp->fileID, irp->inputBufferLength, irp->offset));
	finfo = disk_get_file_info(irp->dev, irp->fileID);
	if (finfo == NULL)
	{
		LLOGLN(0, ("disk_read: invalid file id"));
		return RD_STATUS_INVALID_HANDLE;
	}
	if (finfo->is_dir)
		return RD_STATUS_FILE_IS_A_DIRECTORY;
	if (finfo->file == -1)
		return RD_STATUS_INVALID_HANDLE;

	if (lseek(finfo->file, irp->offset, SEEK_SET) == (off_t) - 1)
		return get_error_status();

	len = 0;
	while (len < irp->inputBufferLength)
	{
		r = write(finfo->file, irp->inputBuffer, irp->inputBufferLength);
		if (r == -1)
		{
			return get_error_status();
		}
		len += r;
	}
	return RD_STATUS_SUCCESS;
}
Exemple #2
0
static uint32
disk_read(IRP * irp)
{
	FILE_INFO * finfo;
	char * buf;
	ssize_t r;

	LLOGLN(10, ("disk_read: id=%d len=%d off=%lld", irp->fileID, irp->length, irp->offset));
	finfo = disk_get_file_info(irp->dev, irp->fileID);
	if (finfo == NULL)
	{
		LLOGLN(0, ("disk_read: invalid file id"));
		return RD_STATUS_INVALID_HANDLE;
	}
	if (finfo->is_dir)
		return RD_STATUS_FILE_IS_A_DIRECTORY;
	if (finfo->file == -1)
		return RD_STATUS_INVALID_HANDLE;

	if (lseek(finfo->file, irp->offset, SEEK_SET) == (off_t) - 1)
		return get_error_status();

	buf = malloc(irp->length);
	memset(buf, 0, irp->length);
	r = read(finfo->file, buf, irp->length);
	if (r == -1)
	{
		free(buf);
		return get_error_status();
	}
	else
	{
		irp->outputBuffer = buf;
		irp->outputBufferLength = r;
		return RD_STATUS_SUCCESS;
	}
}
Exemple #3
0
static uint32
disk_query_directory(IRP * irp, uint8 initialQuery, const char * path)
{
	DISK_DEVICE_INFO * info;
	FILE_INFO * finfo;
	char * p;
	uint32 status;
	char * buf;
	int size;
	int len;
	struct dirent * pdirent;
	struct stat file_stat;
	uint32 attr;

	LLOGLN(10, ("disk_query_directory: class=%d id=%d init=%d path=%s", irp->infoClass, irp->fileID,
		initialQuery, path));
	finfo = disk_get_file_info(irp->dev, irp->fileID);
	if (finfo == NULL || finfo->dir == NULL)
	{
		LLOGLN(0, ("disk_query_directory: invalid file id"));
		return RD_STATUS_INVALID_HANDLE;
	}
	info = (DISK_DEVICE_INFO *) irp->dev->info;

	if (initialQuery)
	{
		if (finfo->pattern)
			free(finfo->pattern);
		p = strrchr(path, '\\');
		p = (p ? p + 1 : (char *)path);
		finfo->pattern = malloc(strlen(p) + 1);
		strcpy(finfo->pattern, p);
		rewinddir(finfo->dir);
	}

	status = RD_STATUS_SUCCESS;
	buf = NULL;
	size = 0;

	pdirent = readdir(finfo->dir);
	while (pdirent && finfo->pattern[0] && fnmatch(finfo->pattern, pdirent->d_name, 0) != 0)
		pdirent = readdir(finfo->dir);
	if (pdirent == NULL)
	{
		return RD_STATUS_NO_MORE_FILES;
	}		

	memset(&file_stat, 0, sizeof(struct stat));
	p = malloc(strlen(finfo->fullpath) + strlen(pdirent->d_name) + 2);
	sprintf(p, "%s/%s", finfo->fullpath, pdirent->d_name);
	if (stat(p, &file_stat) != 0)
	{
		LLOGLN(0, ("disk_query_directory: stat %s failed (%i)\n", p, errno));
	}
	free(p);

	attr = get_file_attribute(pdirent->d_name, &file_stat);

	switch (irp->infoClass)
	{
		case FileBothDirectoryInformation:
			size = 93 + strlen(pdirent->d_name) * 2;
			buf = malloc(size);
			memset(buf, 0, size);

			SET_UINT32(buf, 0, 0); /* NextEntryOffset */
			SET_UINT32(buf, 4, 0); /* FileIndex */
			SET_UINT64(buf, 8, get_rdp_filetime(file_stat.st_ctime < file_stat.st_mtime ?
				file_stat.st_ctime : file_stat.st_mtime)); /* CreationTime */
			SET_UINT64(buf, 16, get_rdp_filetime(file_stat.st_atime)); /* LastAccessTime */
			SET_UINT64(buf, 24, get_rdp_filetime(file_stat.st_mtime)); /* LastWriteTime */
			SET_UINT64(buf, 32, get_rdp_filetime(file_stat.st_ctime)); /* ChangeTime */
			SET_UINT64(buf, 40, file_stat.st_size); /* EndOfFile */
			SET_UINT64(buf, 48, file_stat.st_size); /* AllocationSize */
			SET_UINT32(buf, 56, attr); /* FileAttributes */
			SET_UINT32(buf, 64, 0); /* EaSize */
			SET_UINT8(buf, 68, 0); /* ShortNameLength */
			/* [MS-FSCC] has one byte padding here but RDP does not! */
			//SET_UINT8(buf, 69, 0); /* Reserved */
			/* ShortName 24  bytes */
			len = freerdp_set_wstr(buf + 93, size - 93, pdirent->d_name, strlen(pdirent->d_name));
			SET_UINT32(buf, 60, len); /* FileNameLength */
			size = 93 + len;
			break;

		case FileFullDirectoryInformation:
			size = 68 + strlen(pdirent->d_name) * 2;
			buf = malloc(size);
			memset(buf, 0, size);

			SET_UINT32(buf, 0, 0); /* NextEntryOffset */
			SET_UINT32(buf, 4, 0); /* FileIndex */
			SET_UINT64(buf, 8, get_rdp_filetime(file_stat.st_ctime < file_stat.st_mtime ?
				file_stat.st_ctime : file_stat.st_mtime)); /* CreationTime */
			SET_UINT64(buf, 16, get_rdp_filetime(file_stat.st_atime)); /* LastAccessTime */
			SET_UINT64(buf, 24, get_rdp_filetime(file_stat.st_mtime)); /* LastWriteTime */
			SET_UINT64(buf, 32, get_rdp_filetime(file_stat.st_ctime)); /* ChangeTime */
			SET_UINT64(buf, 40, file_stat.st_size); /* EndOfFile */
			SET_UINT64(buf, 48, file_stat.st_size); /* AllocationSize */
			SET_UINT32(buf, 56, attr); /* FileAttributes */
			SET_UINT32(buf, 64, 0); /* EaSize */
			len = freerdp_set_wstr(buf + 68, size - 68, pdirent->d_name, strlen(pdirent->d_name));
			SET_UINT32(buf, 60, len); /* FileNameLength */
			size = 68 + len;
			break;

		default:
			LLOGLN(0, ("disk_query_directory: invalid info class"));
			status = RD_STATUS_NOT_SUPPORTED;
			break;
	}

	irp->outputBuffer = buf;
	irp->outputBufferLength = size;

	return status;
}
Exemple #4
0
static uint32
disk_set_info(IRP * irp)
{
	FILE_INFO *finfo;
	uint32 status;
	uint64 len;
	char * buf;
	int size;
	char * fullpath;
	struct stat file_stat;
	struct utimbuf tvs;
	int mode;
	uint32 attr;
	time_t t;

	LLOGLN(10, ("disk_set_info: class=%d id=%d", irp->infoClass, irp->fileID));
	finfo = disk_get_file_info(irp->dev, irp->fileID);
	if (finfo == NULL)
	{
		LLOGLN(0, ("disk_set_info: invalid file id"));
		return RD_STATUS_INVALID_HANDLE;
	}

	status = RD_STATUS_SUCCESS;

	switch (irp->infoClass)
	{
		case FileBasicInformation:
			if (stat(finfo->fullpath, &file_stat) != 0)
				return get_error_status();

			/* Change file time */
			tvs.actime = file_stat.st_atime;
			tvs.modtime = file_stat.st_mtime;
			t = get_system_filetime(GET_UINT64(irp->inputBuffer, 8)); /* LastAccessTime */
			if (t > 0)
				tvs.actime = t;
			t = get_system_filetime(GET_UINT64(irp->inputBuffer, 16)); /* LastWriteTime */
			if (t > 0)
				tvs.modtime = t;
			utime(finfo->fullpath, &tvs);

			/* Change read-only flag */
			attr = GET_UINT32(irp->inputBuffer, 32);
			if (attr == 0)
				break;
			mode = file_stat.st_mode;
			if (attr & FILE_ATTRIBUTE_READONLY)
				mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
			else
				mode |= S_IWUSR;
			mode &= 0777;
			chmod(finfo->fullpath, mode);
			break;

		case FileEndOfFileInformation:
		case FileAllocationInformation:
			len = GET_UINT64(irp->inputBuffer, 0);
			set_file_size(finfo->file, len);
			break;

		case FileDispositionInformation:
			/* Delete on close */
			finfo->delete_pending = 1;
			break;

		case FileRenameInformation:
			//replaceIfExists = GET_UINT8(irp->inputBuffer, 0); /* ReplaceIfExists */
			//rootDirectory = GET_UINT8(irp->inputBuffer, 1); /* RootDirectory */
			len = GET_UINT32(irp->inputBuffer, 2);
			size = len * 2;
			buf = malloc(size);
			memset(buf, 0, size);
			freerdp_get_wstr(buf, size, irp->inputBuffer + 6, len);
			fullpath = disk_get_fullpath(irp->dev, buf);
			free(buf);
			LLOGLN(10, ("disk_set_info: rename %s to %s", finfo->fullpath, fullpath));
			if (rename(finfo->fullpath, fullpath) == 0)
			{
				free(finfo->fullpath);
				finfo->fullpath = fullpath;
			}
			else
			{
				free(fullpath);
				return get_error_status();
			}
			break;

		default:
			LLOGLN(0, ("disk_set_info: invalid info class"));
			status = RD_STATUS_NOT_SUPPORTED;
			break;
	}

	return status;
}
Exemple #5
0
static uint32
disk_query_info(IRP * irp)
{
	FILE_INFO *finfo;
	uint32 status;
	int size;
	char * buf;

	LLOGLN(10, ("disk_query_info: class=%d id=%d", irp->infoClass, irp->fileID));
	finfo = disk_get_file_info(irp->dev, irp->fileID);
	if (finfo == NULL)
	{
		LLOGLN(0, ("disk_query_info: invalid file id"));
		return RD_STATUS_INVALID_HANDLE;
	}

	size = 256;
	buf = malloc(size);
	memset(buf, 0, size);

	status = RD_STATUS_SUCCESS;

	switch (irp->infoClass)
	{
		case FileBasicInformation:
			SET_UINT64(buf, 0, get_rdp_filetime(finfo->file_stat.st_ctime < finfo->file_stat.st_mtime ?
				finfo->file_stat.st_ctime : finfo->file_stat.st_mtime)); /* CreationTime */
			SET_UINT64(buf, 8, get_rdp_filetime(finfo->file_stat.st_atime)); /* LastAccessTime */
			SET_UINT64(buf, 16, get_rdp_filetime(finfo->file_stat.st_mtime)); /* LastWriteTime */
			SET_UINT64(buf, 24, get_rdp_filetime(finfo->file_stat.st_ctime)); /* ChangeTime */
			SET_UINT32(buf, 32, finfo->file_attr); /* FileAttributes */
			size = 36;
			break;

		case FileStandardInformation:
			SET_UINT64(buf, 0, finfo->file_stat.st_size); /* AllocationSize */
			SET_UINT64(buf, 8, finfo->file_stat.st_size); /* EndOfFile */
			SET_UINT32(buf, 16, finfo->file_stat.st_nlink); /* NumberOfLinks */
			SET_UINT8(buf, 20, 0); /* DeletePending */
			SET_UINT8(buf, 21, finfo->is_dir); /* Directory */
			size = 22;
			break;

		case FileObjectIdInformation:
			SET_UINT32(buf, 0, finfo->file_attr); /* FileAttributes */
			SET_UINT32(buf, 4, 0);	/* ReparseTag */
			size = 8;
			break;

		default:
			LLOGLN(0, ("disk_query_info: invalid info class"));
			size = 0;
			status = RD_STATUS_NOT_SUPPORTED;
			break;
	}

	irp->outputBuffer = buf;
	irp->outputBufferLength = size;

	return status;
}
Exemple #6
0
static uint32
disk_query_volume_info(IRP * irp)
{
	FILE_INFO * finfo;
	struct STATFS_T stat_fs;
	uint32 status;
	int size;
	char * buf;
	int len;

	LLOGLN(10, ("disk_query_volume_info: class=%d id=%d", irp->infoClass, irp->fileID));
	finfo = disk_get_file_info(irp->dev, irp->fileID);
	if (finfo == NULL)
	{
		LLOGLN(0, ("disk_query_volume_info: invalid file id"));
		return RD_STATUS_INVALID_HANDLE;
	}
	if (STATFS_FN(finfo->fullpath, &stat_fs) != 0)
	{
		LLOGLN(0, ("disk_query_volume_info: statfs failed"));
		return RD_STATUS_ACCESS_DENIED;
	}

	size = 0;
	buf = NULL;
	status = RD_STATUS_SUCCESS;

	switch (irp->infoClass)
	{
		case FileFsVolumeInformation:
			buf = malloc(256);
			memset(buf, 0, 256);
			SET_UINT64(buf, 0, 0); /* VolumeCreationTime */
			SET_UINT32(buf, 8, 0); /* VolumeSerialNumber */
			len = freerdp_set_wstr(buf + 17, size - 17, "FREERDP", strlen("FREERDP") + 1);
			SET_UINT32(buf, 12, len); /* VolumeLabelLength */
			SET_UINT8(buf, 16, 0);	/* SupportsObjects */
			size = 17 + len;
			break;

		case FileFsSizeInformation:
			size = 24;
			buf = malloc(size);
			memset(buf, 0, size);
			SET_UINT64(buf, 0, stat_fs.f_blocks); /* TotalAllocationUnits */
			SET_UINT64(buf, 8, stat_fs.f_bfree); /* AvailableAllocationUnits */
			SET_UINT32(buf, 16, stat_fs.f_bsize / 0x200); /* SectorsPerAllocationUnit */
			SET_UINT32(buf, 20, 0x200); /* BytesPerSector */
			break;

		case FileFsAttributeInformation:
			buf = malloc(256);
			memset(buf, 0, 256);
			SET_UINT32(buf, 0, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
			SET_UINT32(buf, 4, F_NAMELEN(stat_fs)); /* MaximumComponentNameLength */
			len = freerdp_set_wstr(buf + 12, 256 - 12, "FREERDP", 8);
			SET_UINT32(buf, 8, len); /* FileSystemNameLength */
			size = 12 + len;
			break;

		case FileFsFullSizeInformation:
			size = 32;
			buf = malloc(size);
			memset(buf, 0, size);
			SET_UINT64(buf, 0, stat_fs.f_blocks); /* TotalAllocationUnits */
			SET_UINT64(buf, 8, stat_fs.f_bfree); /* CallerAvailableAllocationUnits */
			SET_UINT64(buf, 16, stat_fs.f_bfree); /* ActualAvailableAllocationUnits */
			SET_UINT32(buf, 24, stat_fs.f_bsize / 0x200); /* SectorsPerAllocationUnit */
			SET_UINT32(buf, 28, 0x200); /* BytesPerSector */
			break;

		case FileFsDeviceInformation:
			size = 8;
			buf = malloc(size);
			memset(buf, 0, size);
			SET_UINT32(buf, 0, FILE_DEVICE_DISK); /* DeviceType */
			SET_UINT32(buf, 4, 0); /* BytesPerSector */
			break;

		default:
			LLOGLN(0, ("disk_query_volume_info: invalid info class"));
			status = RD_STATUS_NOT_SUPPORTED;
			break;
	}

	irp->outputBuffer = buf;
	irp->outputBufferLength = size;

	return status;
}
Exemple #7
0
static int
disk_get_fd(IRP * irp)
{
	FILE_INFO * finfo = disk_get_file_info(irp->dev, irp->fileID);
	return finfo->file;
}