⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disk.c

📁 rdesktop is a client for Microsoft Windows NT Terminal Server, Windows 2000 Terminal Services, Wind
💻 C
📖 第 1 页 / 共 2 页
字号:
	{		perror("stat");		out_uint8(out, 0);		return STATUS_ACCESS_DENIED;	}	/* Set file attributes */	file_attributes = 0;	if (S_ISDIR(filestat.st_mode))		file_attributes |= FILE_ATTRIBUTE_DIRECTORY;	filename = 1 + strrchr(path, '/');	if (filename && filename[0] == '.')		file_attributes |= FILE_ATTRIBUTE_HIDDEN;	if (!file_attributes)		file_attributes |= FILE_ATTRIBUTE_NORMAL;	if (!(filestat.st_mode & S_IWUSR))		file_attributes |= FILE_ATTRIBUTE_READONLY;	/* Return requested data */	switch (info_class)	{		case FileBasicInformation:			seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,						       &ft_low);			out_uint32_le(out, ft_low);	/* create_access_time */			out_uint32_le(out, ft_high);			seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);			out_uint32_le(out, ft_low);	/* last_access_time */			out_uint32_le(out, ft_high);			seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);			out_uint32_le(out, ft_low);	/* last_write_time */			out_uint32_le(out, ft_high);			seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);			out_uint32_le(out, ft_low);	/* last_change_time */			out_uint32_le(out, ft_high);			out_uint32_le(out, file_attributes);			break;		case FileStandardInformation:			out_uint32_le(out, filestat.st_size);	/* Allocation size */			out_uint32_le(out, 0);			out_uint32_le(out, filestat.st_size);	/* End of file */			out_uint32_le(out, 0);			out_uint32_le(out, filestat.st_nlink);	/* Number of links */			out_uint8(out, 0);	/* Delete pending */			out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0);	/* Directory */			break;		case FileObjectIdInformation:			out_uint32_le(out, file_attributes);	/* File Attributes */			out_uint32_le(out, 0);	/* Reparse Tag */			break;		default:			unimpl("IRP Query (File) Information class: 0x%x\n", info_class);			return STATUS_INVALID_PARAMETER;	}	return STATUS_SUCCESS;}NTSTATUSdisk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out){	uint32 length, file_attributes, ft_high, ft_low, delete_on_close;	char newname[PATH_MAX], fullpath[PATH_MAX];	struct fileinfo *pfinfo;	int mode;	struct stat filestat;	time_t write_time, change_time, access_time, mod_time;	struct utimbuf tvs;	struct STATFS_T stat_fs;	pfinfo = &(g_fileinfo[handle]);	g_notify_stamp = True;	switch (info_class)	{		case FileBasicInformation:			write_time = change_time = access_time = 0;			in_uint8s(in, 4);	/* Handle of root dir? */			in_uint8s(in, 24);	/* unknown */			/* CreationTime */			in_uint32_le(in, ft_low);			in_uint32_le(in, ft_high);			/* AccessTime */			in_uint32_le(in, ft_low);			in_uint32_le(in, ft_high);			if (ft_low || ft_high)				access_time = convert_1970_to_filetime(ft_high, ft_low);			/* WriteTime */			in_uint32_le(in, ft_low);			in_uint32_le(in, ft_high);			if (ft_low || ft_high)				write_time = convert_1970_to_filetime(ft_high, ft_low);			/* ChangeTime */			in_uint32_le(in, ft_low);			in_uint32_le(in, ft_high);			if (ft_low || ft_high)				change_time = convert_1970_to_filetime(ft_high, ft_low);			in_uint32_le(in, file_attributes);			if (fstat(handle, &filestat))				return STATUS_ACCESS_DENIED;			tvs.modtime = filestat.st_mtime;			tvs.actime = filestat.st_atime;			if (access_time)				tvs.actime = access_time;			if (write_time || change_time)				mod_time = MIN(write_time, change_time);			else				mod_time = write_time ? write_time : change_time;			if (mod_time)				tvs.modtime = mod_time;			if (access_time || write_time || change_time)			{#if WITH_DEBUG_RDP5				printf("FileBasicInformation access       time %s",				       ctime(&tvs.actime));				printf("FileBasicInformation modification time %s",				       ctime(&tvs.modtime));#endif				if (utime(pfinfo->path, &tvs) && errno != EPERM)					return STATUS_ACCESS_DENIED;			}			if (!file_attributes)				break;	/* not valid */			mode = filestat.st_mode;			if (file_attributes & FILE_ATTRIBUTE_READONLY)				mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);			else				mode |= S_IWUSR;			mode &= 0777;#if WITH_DEBUG_RDP5			printf("FileBasicInformation set access mode 0%o", mode);#endif			if (fchmod(handle, mode))				return STATUS_ACCESS_DENIED;			break;		case FileRenameInformation:			in_uint8s(in, 4);	/* Handle of root dir? */			in_uint8s(in, 0x1a);	/* unknown */			in_uint32_le(in, length);			if (length && (length / 2) < 256)			{				rdp_in_unistr(in, newname, length);				convert_to_unix_filename(newname);			}			else			{				return STATUS_INVALID_PARAMETER;			}			sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,				newname);			if (rename(pfinfo->path, fullpath) != 0)			{				perror("rename");				return STATUS_ACCESS_DENIED;			}			break;		case FileDispositionInformation:			/* As far as I understand it, the correct			   thing to do here is to *schedule* a delete,			   so it will be deleted when the file is			   closed. Subsequent			   FileDispositionInformation requests with			   DeleteFile set to FALSE should unschedule			   the delete. See			   http://www.osronline.com/article.cfm?article=245. */			in_uint32_le(in, delete_on_close);			if (delete_on_close ||			    (pfinfo->			     accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))			{				pfinfo->delete_on_close = True;			}			break;		case FileAllocationInformation:			/* Fall through to FileEndOfFileInformation,			   which uses ftrunc. This is like Samba with			   "strict allocation = false", and means that			   we won't detect out-of-quota errors, for			   example. */		case FileEndOfFileInformation:			in_uint8s(in, 28);	/* unknown */			in_uint32_le(in, length);	/* file size */			/* prevents start of writing if not enough space left on device */			if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)				if (stat_fs.f_bfree * stat_fs.f_bsize < length)					return STATUS_DISK_FULL;			if (ftruncate_growable(handle, length) != 0)			{				return STATUS_DISK_FULL;			}			break;		default:			unimpl("IRP Set File Information class: 0x%x\n", info_class);			return STATUS_INVALID_PARAMETER;	}	return STATUS_SUCCESS;}NTSTATUSdisk_check_notify(NTHANDLE handle){	struct fileinfo *pfinfo;	NTSTATUS status = STATUS_PENDING;	NOTIFY notify;	pfinfo = &(g_fileinfo[handle]);	if (!pfinfo->pdir)		return STATUS_INVALID_DEVICE_REQUEST;	status = NotifyInfo(handle, pfinfo->info_class, &notify);	if (status != STATUS_PENDING)		return status;	if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))	{		/*printf("disk_check_notify found changed event\n"); */		memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));		status = STATUS_NOTIFY_ENUM_DIR;	}	return status;}NTSTATUSdisk_create_notify(NTHANDLE handle, uint32 info_class){	struct fileinfo *pfinfo;	NTSTATUS ret = STATUS_PENDING;	/* printf("start disk_create_notify info_class %X\n", info_class); */	pfinfo = &(g_fileinfo[handle]);	pfinfo->info_class = info_class;	ret = NotifyInfo(handle, info_class, &pfinfo->notify);	if (info_class & 0x1000)	{			/* ???? */		if (ret == STATUS_PENDING)			return STATUS_SUCCESS;	}	/* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */	return ret;}static NTSTATUSNotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p){	struct fileinfo *pfinfo;	struct stat buf;	struct dirent *dp;	char *fullname;	DIR *dpr;	pfinfo = &(g_fileinfo[handle]);	if (fstat(handle, &buf) < 0)	{		perror("NotifyInfo");		return STATUS_ACCESS_DENIED;	}	p->modify_time = buf.st_mtime;	p->status_time = buf.st_ctime;	p->num_entries = 0;	p->total_time = 0;	dpr = opendir(pfinfo->path);	if (!dpr)	{		perror("NotifyInfo");		return STATUS_ACCESS_DENIED;	}	while ((dp = readdir(dpr)))	{		if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))			continue;		p->num_entries++;		fullname = (char *) xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);		sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);		if (!stat(fullname, &buf))		{			p->total_time += (buf.st_mtime + buf.st_ctime);		}		xfree(fullname);	}	closedir(dpr);	return STATUS_PENDING;}static FsInfoType *FsVolumeInfo(char *fpath){	static FsInfoType info;#ifdef USE_SETMNTENT	FILE *fdfs;	struct mntent *e;#endif	/* initialize */	memset(&info, 0, sizeof(info));	strcpy(info.label, "RDESKTOP");	strcpy(info.type, "RDPFS");#ifdef USE_SETMNTENT	fdfs = setmntent(MNTENT_PATH, "r");	if (!fdfs)		return &info;	while ((e = getmntent(fdfs)))	{		if (str_startswith(e->mnt_dir, fpath))		{			strcpy(info.type, e->mnt_type);			strcpy(info.name, e->mnt_fsname);			if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660"))			{				int fd = open(e->mnt_fsname, O_RDONLY);				if (fd >= 0)				{					unsigned char buf[512];					memset(buf, 0, sizeof(buf));					if (strstr(e->mnt_opts, "vfat"))						 /*FAT*/					{						strcpy(info.type, "vfat");						read(fd, buf, sizeof(buf));						info.serial =							(buf[42] << 24) + (buf[41] << 16) +							(buf[40] << 8) + buf[39];						strncpy(info.label, (char *) buf + 43, 10);						info.label[10] = '\0';					}					else if (lseek(fd, 32767, SEEK_SET) >= 0)	/* ISO9660 */					{						read(fd, buf, sizeof(buf));						strncpy(info.label, (char *) buf + 41, 32);						info.label[32] = '\0';						/* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */					}					close(fd);				}			}		}	}	endmntent(fdfs);#else	/* initialize */	memset(&info, 0, sizeof(info));	strcpy(info.label, "RDESKTOP");	strcpy(info.type, "RDPFS");#endif	return &info;}NTSTATUSdisk_query_volume_information(NTHANDLE handle, uint32 info_class, STREAM out){	struct STATFS_T stat_fs;	struct fileinfo *pfinfo;	FsInfoType *fsinfo;	pfinfo = &(g_fileinfo[handle]);	if (STATFS_FN(pfinfo->path, &stat_fs) != 0)	{		perror("statfs");		return STATUS_ACCESS_DENIED;	}	fsinfo = FsVolumeInfo(pfinfo->path);	switch (info_class)	{		case FileFsVolumeInformation:			out_uint32_le(out, 0);	/* volume creation time low */			out_uint32_le(out, 0);	/* volume creation time high */			out_uint32_le(out, fsinfo->serial);	/* serial */			out_uint32_le(out, 2 * strlen(fsinfo->label));	/* length of string */			out_uint8(out, 0);	/* support objects? */			rdp_out_unistr(out, fsinfo->label, 2 * strlen(fsinfo->label) - 2);			break;		case FileFsSizeInformation:			out_uint32_le(out, stat_fs.f_blocks);	/* Total allocation units low */			out_uint32_le(out, 0);	/* Total allocation high units */			out_uint32_le(out, stat_fs.f_bfree);	/* Available allocation units */			out_uint32_le(out, 0);	/* Available allowcation units */			out_uint32_le(out, stat_fs.f_bsize / 0x200);	/* Sectors per allocation unit */			out_uint32_le(out, 0x200);	/* Bytes per sector */			break;		case FileFsAttributeInformation:			out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED);	/* fs attributes */			out_uint32_le(out, F_NAMELEN(stat_fs));	/* max length of filename */			out_uint32_le(out, 2 * strlen(fsinfo->type));	/* length of fs_type */			rdp_out_unistr(out, fsinfo->type, 2 * strlen(fsinfo->type) - 2);			break;		case FileFsLabelInformation:		case FileFsDeviceInformation:		case FileFsControlInformation:		case FileFsFullSizeInformation:		case FileFsObjectIdInformation:		case FileFsMaximumInformation:		default:			unimpl("IRP Query Volume Information class: 0x%x\n", info_class);			return STATUS_INVALID_PARAMETER;	}	return STATUS_SUCCESS;}NTSTATUSdisk_query_directory(NTHANDLE handle, uint32 info_class, char *pattern, STREAM out){	uint32 file_attributes, ft_low, ft_high;	char *dirname, fullpath[PATH_MAX];	DIR *pdir;	struct dirent *pdirent;	struct stat fstat;	struct fileinfo *pfinfo;	pfinfo = &(g_fileinfo[handle]);	pdir = pfinfo->pdir;	dirname = pfinfo->path;	file_attributes = 0;	switch (info_class)	{		case FileBothDirectoryInformation:			/* If a search pattern is received, remember this pattern, and restart search */			if (pattern[0] != 0)			{				strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), PATH_MAX - 1);				rewinddir(pdir);			}			/* find next dirent matching pattern */			pdirent = readdir(pdir);			while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)				pdirent = readdir(pdir);			if (pdirent == NULL)				return STATUS_NO_MORE_FILES;			/* Get information for directory entry */			sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);			if (stat(fullpath, &fstat))			{				switch (errno)				{					case ENOENT:					case ELOOP:					case EACCES:						/* These are non-fatal errors. */						memset(&fstat, 0, sizeof(fstat));						break;					default:						/* Fatal error. By returning STATUS_NO_SUCH_FILE, 						   the directory list operation will be aborted */						perror(fullpath);						out_uint8(out, 0);						return STATUS_NO_SUCH_FILE;				}			}			if (S_ISDIR(fstat.st_mode))				file_attributes |= FILE_ATTRIBUTE_DIRECTORY;			if (pdirent->d_name[0] == '.')				file_attributes |= FILE_ATTRIBUTE_HIDDEN;			if (!file_attributes)				file_attributes |= FILE_ATTRIBUTE_NORMAL;			if (!(fstat.st_mode & S_IWUSR))				file_attributes |= FILE_ATTRIBUTE_READONLY;			/* Return requested information */			out_uint8s(out, 8);	/* unknown zero */			seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);			out_uint32_le(out, ft_low);	/* create time */			out_uint32_le(out, ft_high);			seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);			out_uint32_le(out, ft_low);	/* last_access_time */			out_uint32_le(out, ft_high);			seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);			out_uint32_le(out, ft_low);	/* last_write_time */			out_uint32_le(out, ft_high);			seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);			out_uint32_le(out, ft_low);	/* change_write_time */			out_uint32_le(out, ft_high);			out_uint32_le(out, fstat.st_size);	/* filesize low */			out_uint32_le(out, 0);	/* filesize high */			out_uint32_le(out, fstat.st_size);	/* filesize low */			out_uint32_le(out, 0);	/* filesize high */			out_uint32_le(out, file_attributes);			out_uint8(out, 2 * strlen(pdirent->d_name) + 2);	/* unicode length */			out_uint8s(out, 7);	/* pad? */			out_uint8(out, 0);	/* 8.3 file length */			out_uint8s(out, 2 * 12);	/* 8.3 unicode length */			rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));			break;		default:			/* FIXME: Support FileDirectoryInformation,			   FileFullDirectoryInformation, and			   FileNamesInformation */			unimpl("IRP Query Directory sub: 0x%x\n", info_class);			return STATUS_INVALID_PARAMETER;	}	return STATUS_SUCCESS;}static NTSTATUSdisk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out){	if (((request >> 16) != 20) || ((request >> 16) != 9))		return STATUS_INVALID_PARAMETER;	/* extract operation */	request >>= 2;	request &= 0xfff;	printf("DISK IOCTL %d\n", request);	switch (request)	{		case 25:	/* ? */		case 42:	/* ? */		default:			unimpl("DISK IOCTL %d\n", request);			return STATUS_INVALID_PARAMETER;	}	return STATUS_SUCCESS;}DEVICE_FNS disk_fns = {	disk_create,	disk_close,	disk_read,	disk_write,	disk_device_control	/* device_control */};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -