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

📄 proc.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 5 页
字号:
	result = -ENOENT;	if (!inode) {		printk(KERN_ERR "smb_open: no inode for dentry %s/%s\n",		       DENTRY_PATH(dentry));		goto out;	}	if (!smb_is_open(inode)) {		struct smb_sb_info *server = server_from_inode(inode);		smb_lock_server(server);		result = 0;		if (!smb_is_open(inode))			result = smb_proc_open(server, dentry, wish);		smb_unlock_server(server);		if (result) {			PARANOIA("%s/%s open failed, result=%d\n",				 DENTRY_PATH(dentry), result);			goto out;		}		/*		 * A successful open means the path is still valid ...		 */		smb_renew_times(dentry);	}	/*	 * Check whether the access is compatible with the desired mode.	 */	result = 0;	if (inode->u.smbfs_i.access != wish && 	    inode->u.smbfs_i.access != SMB_O_RDWR)	{		PARANOIA("%s/%s access denied, access=%x, wish=%x\n",			 DENTRY_PATH(dentry), inode->u.smbfs_i.access, wish);		result = -EACCES;	}out:	return result;}/* We're called with the server locked */static int smb_proc_close(struct smb_sb_info *server, __u16 fileid, __u32 mtime){	smb_setup_header(server, SMBclose, 3, 0);	WSET(server->packet, smb_vwv0, fileid);	DSET(server->packet, smb_vwv1, utc2local(server, mtime));	return smb_request_ok(server, SMBclose, 0, 0);}/* * Called with the server locked. * * Win NT 4.0 has an apparent bug in that it fails to update the * modify time when writing to a file. As a workaround, we update * both modify and access time locally, and post the times to the * server when closing the file. */static int smb_proc_close_inode(struct smb_sb_info *server, struct inode * ino){	int result = 0;	if (smb_is_open(ino))	{		/*		 * We clear the open flag in advance, in case another 		 * process observes the value while we block below.		 */		ino->u.smbfs_i.open = 0;		/*		 * Kludge alert: SMB timestamps are accurate only to		 * two seconds ... round the times to avoid needless		 * cache invalidations!		 */		if (ino->i_mtime & 1)			ino->i_mtime--;		if (ino->i_atime & 1)			ino->i_atime--;		/*		 * If the file is open with write permissions,		 * update the time stamps to sync mtime and atime.		 */		if ((server->opt.protocol >= SMB_PROTOCOL_LANMAN2) &&		    !(ino->u.smbfs_i.access == SMB_O_RDONLY))		{			struct smb_fattr fattr;			smb_get_inode_attr(ino, &fattr);			smb_proc_setattr_ext(server, ino, &fattr);		}		result = smb_proc_close(server, ino->u.smbfs_i.fileid,						ino->i_mtime);		/*		 * Force a revalidation after closing ... some servers		 * don't post the size until the file has been closed.		 */		if (server->opt.protocol < SMB_PROTOCOL_NT1)			ino->u.smbfs_i.oldmtime = 0;		ino->u.smbfs_i.closed = jiffies;	}	return result;}intsmb_close(struct inode *ino){	int result = 0;	if (smb_is_open(ino)) {		struct smb_sb_info *server = server_from_inode(ino);		smb_lock_server(server);		result = smb_proc_close_inode(server, ino);		smb_unlock_server(server);	}	return result;}/* * This is used to close a file following a failed instantiate. * Since we don't have an inode, we can't use any of the above. */intsmb_close_fileid(struct dentry *dentry, __u16 fileid){	struct smb_sb_info *server = server_from_dentry(dentry);	int result;	smb_lock_server(server);	result = smb_proc_close(server, fileid, CURRENT_TIME);	smb_unlock_server(server);	return result;}/* In smb_proc_read and smb_proc_write we do not retry, because the   file-id would not be valid after a reconnection. */intsmb_proc_read(struct inode *inode, off_t offset, int count, char *data){	struct smb_sb_info *server = server_from_inode(inode);	__u16 returned_count, data_len;	unsigned char *buf;	int result;	smb_lock_server(server);	smb_setup_header(server, SMBread, 5, 0);	buf = server->packet;	WSET(buf, smb_vwv0, inode->u.smbfs_i.fileid);	WSET(buf, smb_vwv1, count);	DSET(buf, smb_vwv2, offset);	WSET(buf, smb_vwv4, 0);	result = smb_request_ok(server, SMBread, 5, -1);	if (result < 0)		goto out;	returned_count = WVAL(server->packet, smb_vwv0);	buf = SMB_BUF(server->packet);	data_len = WVAL(buf, 1);	/* we can NOT simply trust the data_len given by the server ... */	if (data_len > server->packet_size - (buf+3 - server->packet)) {		printk(KERN_ERR "smb_proc_read: invalid data length!! "		       "%d > %d - (%p - %p)\n",		       data_len, server->packet_size, buf+3, server->packet);		result = -EIO;		goto out;	}	memcpy(data, buf+3, data_len);	if (returned_count != data_len) {		printk(KERN_NOTICE "smb_proc_read: returned != data_len\n");		printk(KERN_NOTICE "smb_proc_read: ret_c=%d, data_len=%d\n",		       returned_count, data_len);	}	result = data_len;out:	VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",		inode->i_ino, inode->u.smbfs_i.fileid, count, result);	smb_unlock_server(server);	return result;}intsmb_proc_write(struct inode *inode, off_t offset, int count, const char *data){	struct smb_sb_info *server = server_from_inode(inode);	int result;	__u8 *p;	__u16 fileid = inode->u.smbfs_i.fileid;	VERBOSE("ino=%ld, fileid=%d, count=%d@%ld, packet_size=%d\n",		inode->i_ino, inode->u.smbfs_i.fileid, count, offset,		server->packet_size);	smb_lock_server(server);	p = smb_setup_header(server, SMBwrite, 5, count + 3);	WSET(server->packet, smb_vwv0, fileid);	WSET(server->packet, smb_vwv1, count);	DSET(server->packet, smb_vwv2, offset);	WSET(server->packet, smb_vwv4, 0);	*p++ = 1;	WSET(p, 0, count);	memcpy(p+2, data, count);	result = smb_request_ok(server, SMBwrite, 1, 0);	if (result >= 0)		result = WVAL(server->packet, smb_vwv0);	smb_unlock_server(server);	return result;}intsmb_proc_create(struct dentry *dentry, __u16 attr, time_t ctime, __u16 *fileid){	struct smb_sb_info *server = server_from_dentry(dentry);	char *p;	int result;	smb_lock_server(server);      retry:	p = smb_setup_header(server, SMBcreate, 3, 0);	WSET(server->packet, smb_vwv0, attr);	DSET(server->packet, smb_vwv1, utc2local(server, ctime));	result = smb_simple_encode_path(server, &p, dentry, NULL);	if (result < 0)		goto out;	smb_setup_bcc(server, p);	result = smb_request_ok(server, SMBcreate, 1, 0);	if (result < 0) {		if (smb_retry(server))			goto retry;		goto out;	}	*fileid = WVAL(server->packet, smb_vwv0);	result = 0;out:	smb_unlock_server(server);	return result;}intsmb_proc_mv(struct dentry *old_dentry, struct dentry *new_dentry){	struct smb_sb_info *server = server_from_dentry(old_dentry);	char *p;	int result;	smb_lock_server(server);      retry:	p = smb_setup_header(server, SMBmv, 1, 0);	WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN | aDIR);	result = smb_simple_encode_path(server, &p, old_dentry, NULL);	if (result < 0)		goto out;	result = smb_simple_encode_path(server, &p, new_dentry, NULL);	if (result < 0)		goto out;	smb_setup_bcc(server, p);	if ((result = smb_request_ok(server, SMBmv, 0, 0)) < 0) {		if (smb_retry(server))			goto retry;		goto out;	}	result = 0;out:	smb_unlock_server(server);	return result;}/* * Code common to mkdir and rmdir. */static intsmb_proc_generic_command(struct dentry *dentry, __u8 command){	struct smb_sb_info *server = server_from_dentry(dentry);	char *p;	int result;	smb_lock_server(server);      retry:	p = smb_setup_header(server, command, 0, 0);	result = smb_simple_encode_path(server, &p, dentry, NULL);	if (result < 0)		goto out;	smb_setup_bcc(server, p);	result = smb_request_ok(server, command, 0, 0);	if (result < 0) {		if (smb_retry(server))			goto retry;		goto out;	}	result = 0;out:	smb_unlock_server(server);	return result;}intsmb_proc_mkdir(struct dentry *dentry){	return smb_proc_generic_command(dentry, SMBmkdir);}intsmb_proc_rmdir(struct dentry *dentry){	return smb_proc_generic_command(dentry, SMBrmdir);}#if SMBFS_POSIX_UNLINK/* * Removes readonly attribute from a file. Used by unlink to give posix * semantics. * Note: called with the server locked. */static intsmb_set_rw(struct dentry *dentry,struct smb_sb_info *server){	int result;	struct smb_fattr fattr;	/* first get current attribute */	result = smb_proc_do_getattr(server, dentry, &fattr);	if (result < 0)		return result;	/* if RONLY attribute is set, remove it */	if (fattr.attr & aRONLY) {  /* read only attribute is set */		fattr.attr &= ~aRONLY;		result = smb_proc_setattr_core(server, dentry, fattr.attr);	}	return result;}#endifintsmb_proc_unlink(struct dentry *dentry){	struct smb_sb_info *server = server_from_dentry(dentry);	int flag = 0;	char *p;	int result;	smb_lock_server(server);      retry:	p = smb_setup_header(server, SMBunlink, 1, 0);	WSET(server->packet, smb_vwv0, aSYSTEM | aHIDDEN);	result = smb_simple_encode_path(server, &p, dentry, NULL);	if (result < 0)		goto out;	smb_setup_bcc(server, p);	if ((result = smb_request_ok(server, SMBunlink, 0, 0)) < 0) {#if SMBFS_POSIX_UNLINK		if (result == -EACCES && !flag) {			/* Posix semantics is for the read-only state			   of a file to be ignored in unlink(). In the			   SMB world a unlink() is refused on a			   read-only file. To make things easier for			   unix users we try to override the files			   permission if the unlink fails with the			   right error.			   This introduces a race condition that could			   lead to a file being written by someone who			   shouldn't have access, but as far as I can			   tell that is unavoidable */			/* remove RONLY attribute and try again */			result = smb_set_rw(dentry,server);			if (result == 0) {				flag = 1;				goto retry;			}		}#endif		if (smb_retry(server))			goto retry;		goto out;	}	result = 0;out:	smb_unlock_server(server);	return result;}/* * Called with the server locked */intsmb_proc_flush(struct smb_sb_info *server, __u16 fileid){	smb_setup_header(server, SMBflush, 1, 0);	WSET(server->packet, smb_vwv0, fileid);	return smb_request_ok(server, SMBflush, 0, 0);}intsmb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length){	char *p;	int result;	smb_lock_server(server);retry:	p = smb_setup_header(server, SMBwrite, 5, 3);	WSET(server->packet, smb_vwv0, fid);	WSET(server->packet, smb_vwv1, 0);	DSET(server->packet, smb_vwv2, length);	WSET(server->packet, smb_vwv4, 0);	*p++ = 1;	WSET(p, 0, 0);	if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) {		if (smb_retry(server))			goto retry;		goto out;	}	/*	 * win9x doesn't appear to update the size immediately.	 * It will return the old file size after the truncate,	 * confusing smbfs.	 * NT and Samba return the new value immediately.	 */	if (server->mnt->flags & SMB_MOUNT_WIN95)		smb_proc_flush(server, fid);out:	smb_unlock_server(server);	return result;}static voidsmb_init_dirent(struct smb_sb_info *server, struct smb_fattr *fattr){	memset(fattr, 0, sizeof(*fattr));	fattr->f_nlink = 1;	fattr->f_uid = server->mnt->uid;	fattr->f_gid = server->mnt->gid;	fattr->f_blksize = SMB_ST_BLKSIZE;}static voidsmb_finish_dirent(struct smb_sb_info *server, struct smb_fattr *fattr){	fattr->f_mode = server->mnt->file_mode;	if (fattr->attr & aDIR)	{		fattr->f_mode = server->mnt->dir_mode;		fattr->f_size = SMB_ST_BLKSIZE;	}	/* Check the read-only flag */	if (fattr->attr & aRONLY)		fattr->f_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);	/* How many 512 byte blocks do we need for this file? */	fattr->f_blocks = 0;	if (fattr->f_size != 0)		fattr->f_blocks = 1 + ((fattr->f_size-1) >> 9);	return;}voidsmb_init_root_dirent(struct smb_sb_info *server, struct smb_fattr *fattr){	smb_init_dirent(server, fattr);	fattr->attr = aDIR;	fattr->f_ino = 2; /* traditional root inode number */	fattr->f_mtime = CURRENT_TIME;	smb_finish_dirent(server, fattr);}/* * Decode a dirent for old protocols * * qname is filled with the decoded, and possibly translated, name. * fattr receives decoded attributes * * Bugs Noted: * (1) Pathworks servers may pad the name with extra spaces. */static char *smb_decode_short_dirent(struct smb_sb_info *server, char *p,			struct qstr *qname, struct smb_fattr *fattr){	int len;	/*	 * SMB doesn't have a concept of inode numbers ...	 */	smb_init_dirent(server, fattr);	fattr->f_ino = 0;	/* FIXME: do we need this? */	p += SMB_STATUS_SIZE;	/* reserved (search_status) */	fattr->attr = *p;	fattr->f_mtime = date_dos2unix(server, WVAL(p, 3), WVAL(p, 1));	fattr->f_size = DVAL(p, 5);	fattr->f_ctime = fattr->f_mtime;	fattr->f_atime = fattr->f_mtime;	qname->name = p + 9;	len = strnlen(qname->name, 12);

⌨️ 快捷键说明

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