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

📄 proc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	ts.tv_nsec = do_div(t, 10000000) * 100;	ts.tv_sec = t; 	return ts;}/* Convert the Unix UTC into NT time */static u64smb_unixutc2ntutc(struct timespec ts){	/* Note: timezone conversion is probably wrong. */	/* return ((u64)utc2local(server, t)) * 10000000 + NTFS_TIME_OFFSET; */	return ((u64)ts.tv_sec) * 10000000 + ts.tv_nsec/100 + NTFS_TIME_OFFSET;}#define MAX_FILE_MODE	6static mode_t file_mode[] = {	S_IFREG, S_IFDIR, S_IFLNK, S_IFCHR, S_IFBLK, S_IFIFO, S_IFSOCK};static int smb_filetype_to_mode(u32 filetype){	if (filetype > MAX_FILE_MODE) {		PARANOIA("Filetype out of range: %d\n", filetype);		return S_IFREG;	}	return file_mode[filetype];}static u32 smb_filetype_from_mode(int mode){	if (S_ISREG(mode))		return UNIX_TYPE_FILE;	if (S_ISDIR(mode))		return UNIX_TYPE_DIR;	if (S_ISLNK(mode))		return UNIX_TYPE_SYMLINK;	if (S_ISCHR(mode))		return UNIX_TYPE_CHARDEV;	if (S_ISBLK(mode))		return UNIX_TYPE_BLKDEV;	if (S_ISFIFO(mode))		return UNIX_TYPE_FIFO;	if (S_ISSOCK(mode))		return UNIX_TYPE_SOCKET;	return UNIX_TYPE_UNKNOWN;}/*****************************************************************************//*                                                                           *//*  Support section.                                                         *//*                                                                           *//*****************************************************************************/__u32smb_len(__u8 * p){	return ((*(p+1) & 0x1) << 16L) | (*(p+2) << 8L) | *(p+3);}static __u16smb_bcc(__u8 * packet){	int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(__u16);	return WVAL(packet, pos);}/* smb_valid_packet: We check if packet fulfills the basic   requirements of a smb packet */static intsmb_valid_packet(__u8 * packet){	return (packet[4] == 0xff		&& packet[5] == 'S'		&& packet[6] == 'M'		&& packet[7] == 'B'		&& (smb_len(packet) + 4 == SMB_HEADER_LEN		    + SMB_WCT(packet) * 2 + smb_bcc(packet)));}/* smb_verify: We check if we got the answer we expected, and if we   got enough data. If bcc == -1, we don't care. */static intsmb_verify(__u8 * packet, int command, int wct, int bcc){	if (SMB_CMD(packet) != command)		goto bad_command;	if (SMB_WCT(packet) < wct)		goto bad_wct;	if (bcc != -1 && smb_bcc(packet) < bcc)		goto bad_bcc;	return 0;bad_command:	printk(KERN_ERR "smb_verify: command=%x, SMB_CMD=%x??\n",	       command, SMB_CMD(packet));	goto fail;bad_wct:	printk(KERN_ERR "smb_verify: command=%x, wct=%d, SMB_WCT=%d??\n",	       command, wct, SMB_WCT(packet));	goto fail;bad_bcc:	printk(KERN_ERR "smb_verify: command=%x, bcc=%d, SMB_BCC=%d??\n",	       command, bcc, smb_bcc(packet));fail:	return -EIO;}/* * Returns the maximum read or write size for the "payload". Making all of the * packet fit within the negotiated max_xmit size. * * N.B. Since this value is usually computed before locking the server, * the server's packet size must never be decreased! */static inline intsmb_get_xmitsize(struct smb_sb_info *server, int overhead){	return server->opt.max_xmit - overhead;}/* * Calculate the maximum read size */intsmb_get_rsize(struct smb_sb_info *server){	/* readX has 12 parameters, read has 5 */	int overhead = SMB_HEADER_LEN + 12 * sizeof(__u16) + 2 + 1 + 2;	int size = smb_get_xmitsize(server, overhead);	VERBOSE("xmit=%d, size=%d\n", server->opt.max_xmit, size);	return size;}/* * Calculate the maximum write size */intsmb_get_wsize(struct smb_sb_info *server){	/* writeX has 14 parameters, write has 5 */	int overhead = SMB_HEADER_LEN + 14 * sizeof(__u16) + 2 + 1 + 2;	int size = smb_get_xmitsize(server, overhead);	VERBOSE("xmit=%d, size=%d\n", server->opt.max_xmit, size);	return size;}/* * Convert SMB error codes to -E... errno values. */intsmb_errno(struct smb_request *req){	int errcls = req->rq_rcls;	int error  = req->rq_err;	char *class = "Unknown";	VERBOSE("errcls %d  code %d  from command 0x%x\n",		errcls, error, SMB_CMD(req->rq_header));	if (errcls == ERRDOS) {		switch (error) {		case ERRbadfunc:			return -EINVAL;		case ERRbadfile:		case ERRbadpath:			return -ENOENT;		case ERRnofids:			return -EMFILE;		case ERRnoaccess:			return -EACCES;		case ERRbadfid:			return -EBADF;		case ERRbadmcb:			return -EREMOTEIO;		case ERRnomem:			return -ENOMEM;		case ERRbadmem:			return -EFAULT;		case ERRbadenv:		case ERRbadformat:			return -EREMOTEIO;		case ERRbadaccess:			return -EACCES;		case ERRbaddata:			return -E2BIG;		case ERRbaddrive:			return -ENXIO;		case ERRremcd:			return -EREMOTEIO;		case ERRdiffdevice:			return -EXDEV;		case ERRnofiles:			return -ENOENT;		case ERRbadshare:			return -ETXTBSY;		case ERRlock:			return -EDEADLK;		case ERRfilexists:			return -EEXIST;		case ERROR_INVALID_PARAMETER:			return -EINVAL;		case ERROR_DISK_FULL:			return -ENOSPC;		case ERROR_INVALID_NAME:			return -ENOENT;		case ERROR_DIR_NOT_EMPTY:			return -ENOTEMPTY;		case ERROR_NOT_LOCKED:                       return -ENOLCK;		case ERROR_ALREADY_EXISTS:			return -EEXIST;		default:			class = "ERRDOS";			goto err_unknown;		}	} else if (errcls == ERRSRV) {		switch (error) {		/* N.B. This is wrong ... EIO ? */		case ERRerror:			return -ENFILE;		case ERRbadpw:			return -EINVAL;		case ERRbadtype:		case ERRtimeout:			return -EIO;		case ERRaccess:			return -EACCES;		/*		 * This is a fatal error, as it means the "tree ID"		 * for this connection is no longer valid. We map		 * to a special error code and get a new connection.		 */		case ERRinvnid:			return -EBADSLT;		default:			class = "ERRSRV";			goto err_unknown;		}	} else if (errcls == ERRHRD) {		switch (error) {		case ERRnowrite:			return -EROFS;		case ERRbadunit:			return -ENODEV;		case ERRnotready:			return -EUCLEAN;		case ERRbadcmd:		case ERRdata:			return -EIO;		case ERRbadreq:			return -ERANGE;		case ERRbadshare:			return -ETXTBSY;		case ERRlock:			return -EDEADLK;		case ERRdiskfull:			return -ENOSPC;		default:			class = "ERRHRD";			goto err_unknown;		}	} else if (errcls == ERRCMD) {		class = "ERRCMD";	} else if (errcls == SUCCESS) {		return 0;	/* This is the only valid 0 return */	}err_unknown:	printk(KERN_ERR "smb_errno: class %s, code %d from command 0x%x\n",	       class, error, SMB_CMD(req->rq_header));	return -EIO;}/* smb_request_ok: We expect the server to be locked. Then we do the   request and check the answer completely. When smb_request_ok   returns 0, you can be quite sure that everything went well. When   the answer is <=0, the returned number is a valid unix errno. */static intsmb_request_ok(struct smb_request *req, int command, int wct, int bcc){	int result;	req->rq_resp_wct = wct;	req->rq_resp_bcc = bcc;	result = smb_add_request(req);	if (result != 0) {		DEBUG1("smb_request failed\n");		goto out;	}	if (smb_valid_packet(req->rq_header) != 0) {		PARANOIA("invalid packet!\n");		goto out;	}	result = smb_verify(req->rq_header, command, wct, bcc);out:	return result;}/* * This implements the NEWCONN ioctl. It installs the server pid, * sets server->state to CONN_VALID, and wakes up the waiting process. */intsmb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt){	struct file *filp;	struct sock *sk;	int error;	VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);	smb_lock_server(server);	/*	 * Make sure we don't already have a valid connection ...	 */	error = -EINVAL;	if (server->state == CONN_VALID)		goto out;	error = -EACCES;	if (current->uid != server->mnt->mounted_uid && 	    !capable(CAP_SYS_ADMIN))		goto out;	error = -EBADF;	filp = fget(opt->fd);	if (!filp)		goto out;	if (!smb_valid_socket(filp->f_path.dentry->d_inode))		goto out_putf;	server->sock_file = filp;	server->conn_pid = get_pid(task_pid(current));	server->opt = *opt;	server->generation += 1;	server->state = CONN_VALID;	error = 0;	if (server->conn_error) {		/*		 * conn_error is the returncode we originally decided to		 * drop the old connection on. This message should be positive		 * and not make people ask questions on why smbfs is printing		 * error messages ...		 */		printk(KERN_INFO "SMB connection re-established (%d)\n",		       server->conn_error);		server->conn_error = 0;	}	/*	 * Store the server in sock user_data (Only used by sunrpc)	 */	sk = SOCKET_I(filp->f_path.dentry->d_inode)->sk;	sk->sk_user_data = server;	/* chain into the data_ready callback */	server->data_ready = xchg(&sk->sk_data_ready, smb_data_ready);	/* check if we have an old smbmount that uses seconds for the 	   serverzone */	if (server->opt.serverzone > 12*60 || server->opt.serverzone < -12*60)		server->opt.serverzone /= 60;	/* now that we have an established connection we can detect the server	   type and enable bug workarounds */	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)		install_ops(server->ops, &smb_ops_core);	else if (server->opt.protocol == SMB_PROTOCOL_LANMAN2)		install_ops(server->ops, &smb_ops_os2);	else if (server->opt.protocol == SMB_PROTOCOL_NT1 &&		 (server->opt.max_xmit < 0x1000) &&		 !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {		/* FIXME: can we kill the WIN95 flag now? */		server->mnt->flags |= SMB_MOUNT_WIN95;		VERBOSE("detected WIN95 server\n");		install_ops(server->ops, &smb_ops_win95);	} else {		/*		 * Samba has max_xmit 65535		 * NT4spX has max_xmit 4536 (or something like that)		 * win2k has ...		 */		VERBOSE("detected NT1 (Samba, NT4/5) server\n");		install_ops(server->ops, &smb_ops_winNT);	}	/* FIXME: the win9x code wants to modify these ... (seek/trunc bug) */	if (server->mnt->flags & SMB_MOUNT_OLDATTR) {		server->ops->getattr = smb_proc_getattr_core;	} else if (server->mnt->flags & SMB_MOUNT_DIRATTR) {		server->ops->getattr = smb_proc_getattr_ff;	}	/* Decode server capabilities */	if (server->opt.capabilities & SMB_CAP_LARGE_FILES) {		/* Should be ok to set this now, as no one can access the		   mount until the connection has been established. */		SB_of(server)->s_maxbytes = ~0ULL >> 1;		VERBOSE("LFS enabled\n");	}	if (server->opt.capabilities & SMB_CAP_UNICODE) {		server->mnt->flags |= SMB_MOUNT_UNICODE;		VERBOSE("Unicode enabled\n");	} else {		server->mnt->flags &= ~SMB_MOUNT_UNICODE;	}#if 0	/* flags we may test for other patches ... */	if (server->opt.capabilities & SMB_CAP_LARGE_READX) {		VERBOSE("Large reads enabled\n");	}	if (server->opt.capabilities & SMB_CAP_LARGE_WRITEX) {		VERBOSE("Large writes enabled\n");	}#endif	if (server->opt.capabilities & SMB_CAP_UNIX) {		struct inode *inode;		VERBOSE("Using UNIX CIFS extensions\n");		install_ops(server->ops, &smb_ops_unix);		inode = SB_of(server)->s_root->d_inode;		if (inode)			inode->i_op = &smb_dir_inode_operations_unix;	}	VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",		server->opt.protocol, server->opt.max_xmit,		pid_nr(server->conn_pid), server->opt.capabilities);	/* FIXME: this really should be done by smbmount. */	if (server->opt.max_xmit > SMB_MAX_PACKET_SIZE) {		server->opt.max_xmit = SMB_MAX_PACKET_SIZE;	}	smb_unlock_server(server);	smbiod_wake_up();	if (server->opt.capabilities & SMB_CAP_UNIX)		smb_proc_query_cifsunix(server);	server->conn_complete++;	wake_up_interruptible_all(&server->conn_wq);	return error;out:	smb_unlock_server(server);	smbiod_wake_up();	return error;out_putf:	fput(filp);	goto out;}/* smb_setup_header: We completely set up the packet. You only have to   insert the command-specific fields */__u8 *smb_setup_header(struct smb_request *req, __u8 command, __u16 wct, __u16 bcc){	__u32 xmit_len = SMB_HEADER_LEN + wct * sizeof(__u16) + bcc + 2;	__u8 *p = req->rq_header;	struct smb_sb_info *server = req->rq_server;	p = smb_encode_smb_length(p, xmit_len - 4);	*p++ = 0xff;	*p++ = 'S';	*p++ = 'M';	*p++ = 'B';	*p++ = command;	memset(p, '\0', 19);	p += 19;	p += 8;	if (server->opt.protocol > SMB_PROTOCOL_CORE) {		int flags = SMB_FLAGS_CASELESS_PATHNAMES;		int flags2 = SMB_FLAGS2_LONG_PATH_COMPONENTS |			SMB_FLAGS2_EXTENDED_ATTRIBUTES;	/* EA? not really ... */		*(req->rq_header + smb_flg) = flags;		if (server->mnt->flags & SMB_MOUNT_UNICODE)			flags2 |= SMB_FLAGS2_UNICODE_STRINGS;		WSET(req->rq_header, smb_flg2, flags2);	}	*p++ = wct;		/* wct */	p += 2 * wct;	WSET(p, 0, bcc);	/* Include the header in the data to send */	req->rq_iovlen = 1;	req->rq_iov[0].iov_base = req->rq_header;	req->rq_iov[0].iov_len  = xmit_len - bcc;	return req->rq_buffer;}static voidsmb_setup_bcc(struct smb_request *req, __u8 *p){	u16 bcc = p - req->rq_buffer;	u8 *pbcc = req->rq_header + SMB_HEADER_LEN + 2*SMB_WCT(req->rq_header);	WSET(pbcc, 0, bcc);	smb_encode_smb_length(req->rq_header, SMB_HEADER_LEN + 			      2*SMB_WCT(req->rq_header) - 2 + bcc);	/* Include the "bytes" in the data to send */	req->rq_iovlen = 2;	req->rq_iov[1].iov_base = req->rq_buffer;	req->rq_iov[1].iov_len  = bcc;}static intsmb_proc_seek(struct smb_sb_info *server, __u16 fileid,	      __u16 mode, off_t offset){	int result;	struct smb_request *req;

⌨️ 快捷键说明

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