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

📄 disk.c

📁 rdesktop is a client for Microsoft Windows NT Terminal Server, Windows 2000 Terminal Services, Wind
💻 C
📖 第 1 页 / 共 2 页
字号:
/* -*- c-basic-offset: 8 -*-   rdesktop: A Remote Desktop Protocol client.   Disk Redirection   Copyright (C) Jeroen Meijer 2003   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 2 of the License, or   (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; if not, write to the Free Software   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include "disk.h"#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>		/* open, close */#include <dirent.h>		/* opendir, closedir, readdir */#include <fnmatch.h>#include <errno.h>		/* errno */#include <stdio.h>#include <utime.h>#include <time.h>		/* ctime */#if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1))#define DIRFD(a) (dirfd(a))#else#define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)#endif/* TODO: Fix mntent-handling for solaris * #include <sys/mntent.h> */#if (defined(HAVE_MNTENT_H) && defined(HAVE_SETMNTENT))#include <mntent.h>#define MNTENT_PATH "/etc/mtab"#define USE_SETMNTENT#endif#ifdef HAVE_SYS_VFS_H#include <sys/vfs.h>#endif#ifdef HAVE_SYS_STATVFS_H#include <sys/statvfs.h>#endif#ifdef HAVE_SYS_STATFS_H#include <sys/statfs.h>#endif#ifdef HAVE_SYS_PARAM_H#include <sys/param.h>#endif#ifdef HAVE_SYS_MOUNT_H#include <sys/mount.h>#endif#include "rdesktop.h"#ifdef STAT_STATFS3_OSF1#define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))#define STATFS_T statfs#define USE_STATFS#endif#ifdef STAT_STATVFS#define STATFS_FN(path, buf) (statvfs(path,buf))#define STATFS_T statvfs#define USE_STATVFS#endif#ifdef STAT_STATVFS64#define STATFS_FN(path, buf) (statvfs64(path,buf))#define STATFS_T statvfs64#define USE_STATVFS#endif#if (defined(STAT_STATFS2_FS_DATA) || defined(STAT_STATFS2_BSIZE) || defined(STAT_STATFS2_FSIZE))#define STATFS_FN(path, buf) (statfs(path,buf))#define STATFS_T statfs#define USE_STATFS#endif#ifdef STAT_STATFS4#define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf),0))#define STATFS_T statfs#define USE_STATFS#endif#if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMEMAX)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMEMAX)))#define F_NAMELEN(buf) ((buf).f_namemax)#endif#if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMELEN)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMELEN)))#define F_NAMELEN(buf) ((buf).f_namelen)#endif#ifndef F_NAMELEN#define F_NAMELEN(buf) (255)#endif/* Dummy statfs fallback */#ifndef STATFS_Tstruct dummy_statfs_t{	long f_bfree;	long f_bsize;	long f_blocks;	int f_namelen;	int f_namemax;};static intdummy_statfs(struct dummy_statfs_t *buf){	buf->f_blocks = 262144;	buf->f_bfree = 131072;	buf->f_bsize = 512;	buf->f_namelen = 255;	buf->f_namemax = 255;	return 0;}#define STATFS_T dummy_statfs_t#define STATFS_FN(path,buf) (dummy_statfs(buf))#endifextern RDPDR_DEVICE g_rdpdr_device[];FILEINFO g_fileinfo[MAX_OPEN_FILES];BOOL g_notify_stamp = False;typedef struct{	char name[PATH_MAX];	char label[PATH_MAX];	unsigned long serial;	char type[PATH_MAX];} FsInfoType;static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);static time_tget_create_time(struct stat *st){	time_t ret, ret1;	ret = MIN(st->st_ctime, st->st_mtime);	ret1 = MIN(ret, st->st_atime);	if (ret1 != (time_t) 0)		return ret1;	return ret;}/* Convert seconds since 1970 to a filetime */static voidseconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low){	unsigned long long ticks;	ticks = (seconds + 11644473600LL) * 10000000;	*low = (uint32) ticks;	*high = (uint32) (ticks >> 32);}/* Convert seconds since 1970 back to filetime */static time_tconvert_1970_to_filetime(uint32 high, uint32 low){	unsigned long long ticks;	time_t val;	ticks = low + (((unsigned long long) high) << 32);	ticks /= 10000000;	ticks -= 11644473600LL;	val = (time_t) ticks;	return (val);}/* A wrapper for ftruncate which supports growing files, even if the   native ftruncate doesn't. This is needed on Linux FAT filesystems,   for example. */static intftruncate_growable(int fd, off_t length){	int ret;	off_t pos;	static const char zero = 0;	/* Try the simple method first */	if ((ret = ftruncate(fd, length)) != -1)	{		return ret;	}	/*	 * Some kind of error. Perhaps we were trying to grow. Retry	 * in a safe way.	 */	/* Get current position */	if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)	{		perror("lseek");		return -1;	}	/* Seek to new size */	if (lseek(fd, length, SEEK_SET) == -1)	{		perror("lseek");		return -1;	}	/* Write a zero */	if (write(fd, &zero, 1) == -1)	{		perror("write");		return -1;	}	/* Truncate. This shouldn't fail. */	if (ftruncate(fd, length) == -1)	{		perror("ftruncate");		return -1;	}	/* Restore position */	if (lseek(fd, pos, SEEK_SET) == -1)	{		perror("lseek");		return -1;	}	return 0;}/* Just like open(2), but if a open with O_EXCL fails, retry with   GUARDED semantics. This might be necessary because some filesystems   (such as NFS filesystems mounted from a unfsd server) doesn't   support O_EXCL. GUARDED semantics are subject to race conditions,   but we can live with that.*/static intopen_weak_exclusive(const char *pathname, int flags, mode_t mode){	int ret;	struct stat statbuf;	ret = open(pathname, flags, mode);	if (ret != -1 || !(flags & O_EXCL))	{		/* Success, or not using O_EXCL */		return ret;	}	/* An error occured, and we are using O_EXCL. In case the FS	   doesn't support O_EXCL, some kind of error will be	   returned. Unfortunately, we don't know which one. Linux	   2.6.8 seems to return 524, but I cannot find a documented	   #define for this case. So, we'll return only on errors that	   we know aren't related to O_EXCL. */	switch (errno)	{		case EACCES:		case EEXIST:		case EINTR:		case EISDIR:		case ELOOP:		case ENAMETOOLONG:		case ENOENT:		case ENOTDIR:			return ret;	}	/* Retry with GUARDED semantics */	if (stat(pathname, &statbuf) != -1)	{		/* File exists */		errno = EEXIST;		return -1;	}	else	{		return open(pathname, flags & ~O_EXCL, mode);	}}/* Enumeration of devices from rdesktop.c        *//* returns numer of units found and initialized. *//* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' *//* when it arrives to this function.             */intdisk_enum_devices(uint32 * id, char *optarg){	char *pos = optarg;	char *pos2;	int count = 0;	/* skip the first colon */	optarg++;	while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)	{		pos2 = next_arg(optarg, '=');		strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1);		if (strlen(optarg) > (sizeof(g_rdpdr_device[*id].name) - 1))			fprintf(stderr, "share name %s truncated to %s\n", optarg,				g_rdpdr_device[*id].name);		g_rdpdr_device[*id].local_path = (char *) xmalloc(strlen(pos2) + 1);		strcpy(g_rdpdr_device[*id].local_path, pos2);		g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;		count++;		(*id)++;		optarg = pos;	}	return count;}/* Opens or creates a file or directory */static NTSTATUSdisk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,	    uint32 flags_and_attributes, char *filename, NTHANDLE * phandle){	NTHANDLE handle;	DIR *dirp;	int flags, mode;	char path[PATH_MAX];	struct stat filestat;	handle = 0;	dirp = NULL;	flags = 0;	mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;	if (*filename && filename[strlen(filename) - 1] == '/')		filename[strlen(filename) - 1] = 0;	sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);	switch (create_disposition)	{		case CREATE_ALWAYS:			/* Delete existing file/link. */			unlink(path);			flags |= O_CREAT;			break;		case CREATE_NEW:			/* If the file already exists, then fail. */			flags |= O_CREAT | O_EXCL;			break;		case OPEN_ALWAYS:			/* Create if not already exists. */			flags |= O_CREAT;			break;		case OPEN_EXISTING:			/* Default behaviour */			break;		case TRUNCATE_EXISTING:			/* If the file does not exist, then fail. */			flags |= O_TRUNC;			break;	}	/*printf("Open: \"%s\"  flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); */	/* Get information about file and set that flag ourselfs */	if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))	{		if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)			return STATUS_FILE_IS_A_DIRECTORY;		else			flags_and_attributes |= FILE_DIRECTORY_FILE;	}	if (flags_and_attributes & FILE_DIRECTORY_FILE)	{		if (flags & O_CREAT)		{			mkdir(path, mode);		}		dirp = opendir(path);		if (!dirp)		{			switch (errno)			{				case EACCES:					return STATUS_ACCESS_DENIED;				case ENOENT:					return STATUS_NO_SUCH_FILE;				default:					perror("opendir");					return STATUS_NO_SUCH_FILE;			}		}		handle = DIRFD(dirp);	}	else	{		if (accessmask & GENERIC_ALL		    || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))		{			flags |= O_RDWR;		}		else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))		{			flags |= O_WRONLY;		}		else		{			flags |= O_RDONLY;		}		handle = open_weak_exclusive(path, flags, mode);		if (handle == -1)		{			switch (errno)			{				case EISDIR:					return STATUS_FILE_IS_A_DIRECTORY;				case EACCES:					return STATUS_ACCESS_DENIED;				case ENOENT:					return STATUS_NO_SUCH_FILE;				case EEXIST:					return STATUS_OBJECT_NAME_COLLISION;				default:					perror("open");					return STATUS_NO_SUCH_FILE;			}		}		/* all read and writes of files should be non blocking */		if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)			perror("fcntl");	}	if (handle >= MAX_OPEN_FILES)	{		error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",		      handle);		exit(1);	}	if (dirp)		g_fileinfo[handle].pdir = dirp;	else		g_fileinfo[handle].pdir = NULL;	g_fileinfo[handle].device_id = device_id;	g_fileinfo[handle].flags_and_attributes = flags_and_attributes;	g_fileinfo[handle].accessmask = accessmask;	strncpy(g_fileinfo[handle].path, path, PATH_MAX - 1);	g_fileinfo[handle].delete_on_close = False;	g_notify_stamp = True;	*phandle = handle;	return STATUS_SUCCESS;}static NTSTATUSdisk_close(NTHANDLE handle){	struct fileinfo *pfinfo;	pfinfo = &(g_fileinfo[handle]);	g_notify_stamp = True;	rdpdr_abort_io(handle, 0, STATUS_CANCELLED);	if (pfinfo->pdir)	{		if (closedir(pfinfo->pdir) < 0)		{			perror("closedir");			return STATUS_INVALID_HANDLE;		}		if (pfinfo->delete_on_close)			if (rmdir(pfinfo->path) < 0)			{				perror(pfinfo->path);				return STATUS_ACCESS_DENIED;			}		pfinfo->delete_on_close = False;	}	else	{		if (close(handle) < 0)		{			perror("close");			return STATUS_INVALID_HANDLE;		}		if (pfinfo->delete_on_close)			if (unlink(pfinfo->path) < 0)			{				perror(pfinfo->path);				return STATUS_ACCESS_DENIED;			}		pfinfo->delete_on_close = False;	}	return STATUS_SUCCESS;}static NTSTATUSdisk_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result){	int n;#if 0	/* browsing dir ????        */	/* each request is 24 bytes */	if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE)	{		*result = 0;		return STATUS_SUCCESS;	}#endif	lseek(handle, offset, SEEK_SET);	n = read(handle, data, length);	if (n < 0)	{		*result = 0;		switch (errno)		{			case EISDIR:				/* Implement 24 Byte directory read ??				   with STATUS_NOT_IMPLEMENTED server doesn't read again */				/* return STATUS_FILE_IS_A_DIRECTORY; */				return STATUS_NOT_IMPLEMENTED;			default:				perror("read");				return STATUS_INVALID_PARAMETER;		}	}	*result = n;	return STATUS_SUCCESS;}static NTSTATUSdisk_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result){	int n;	lseek(handle, offset, SEEK_SET);	n = write(handle, data, length);	if (n < 0)	{		perror("write");		*result = 0;		switch (errno)		{			case ENOSPC:				return STATUS_DISK_FULL;			default:				return STATUS_ACCESS_DENIED;		}	}	*result = n;	return STATUS_SUCCESS;}NTSTATUSdisk_query_information(NTHANDLE handle, uint32 info_class, STREAM out){	uint32 file_attributes, ft_high, ft_low;	struct stat filestat;	char *path, *filename;	path = g_fileinfo[handle].path;	/* Get information about file */	if (fstat(handle, &filestat) != 0)

⌨️ 快捷键说明

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