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

📄 proc.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  proc.c * *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke * *  28/06/96 - Fixed long file name support (smb_proc_readdir_long) by Yuri Per */#include <linux/config.h>#include <linux/fs.h>#include <linux/smbno.h>#include <linux/smb_fs.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/malloc.h>#include <linux/stat.h>#include <linux/fcntl.h>#include <asm/segment.h>#include <asm/string.h>#define SMB_VWV(packet)  ((packet) + SMB_HEADER_LEN)#define SMB_CMD(packet)  (BVAL(packet,8))#define SMB_WCT(packet)  (BVAL(packet, SMB_HEADER_LEN - 1))#define SMB_BCC(packet)  smb_bcc(packet)#define SMB_BUF(packet)  ((packet) + SMB_HEADER_LEN + SMB_WCT(packet) * 2 + 2)#define SMB_DIRINFO_SIZE 43#define SMB_STATUS_SIZE  21static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc);static inline intmin(int a, int b){	return a < b ? a : b;}static voidstr_upper(char *name){	while (*name)	{		if (*name >= 'a' && *name <= 'z')			*name -= ('a' - 'A');		name++;	}}static voidstr_lower(char *name){	while (*name)	{		if (*name >= 'A' && *name <= 'Z')			*name += ('a' - 'A');		name++;	}}/*****************************************************************************//*                                                                           *//*  Encoding/Decoding section                                                *//*                                                                           *//*****************************************************************************/static inline byte *smb_decode_word(byte * p, word * data){	*data = WVAL(p, 0);	return p + 2;}byte *smb_encode_smb_length(byte * p, dword len){	BSET(p, 0, 0);	BSET(p, 1, 0);	BSET(p, 2, (len & 0xFF00) >> 8);	BSET(p, 3, (len & 0xFF));	if (len > 0xFFFF)	{		BSET(p, 1, 1);	}	return p + 4;}static byte *smb_encode_ascii(byte * p, const byte * name, int len){	*p++ = 4;	strcpy(p, name);	return p + len + 1;}static byte *smb_encode_this_name(byte * p, const char *name, const int len){	*p++ = '\\';	strncpy(p, name, len);	return p + len;}/* I put smb_encode_parents into a separate function so that the   recursion only takes 16 bytes on the stack per path component on a   386. */static byte *smb_encode_parents(byte * p, struct smb_inode_info *ino){	byte *q;	if (ino->dir == NULL)	{		return p;	}	q = smb_encode_parents(p, ino->dir);	if (q - p + 1 + ino->finfo.len > SMB_MAXPATHLEN)	{		return p;	}	return smb_encode_this_name(q, ino->finfo.name, ino->finfo.len);}static byte *smb_encode_path(struct smb_server *server,		byte * p, struct smb_inode_info *dir,		const char *name, const int len){	byte *start = p;	if (dir != NULL)	{		p = smb_encode_parents(p, dir);	}	p = smb_encode_this_name(p, name, len);	*p++ = 0;	if (server->protocol <= PROTOCOL_COREPLUS)	{		str_upper(start);	}	return p;}static byte *smb_decode_data(byte * p, byte * data, word * data_len, int fs){	word len;	if (!(*p == 1 || *p == 5))	{		printk("smb_decode_data: Warning! Data block not starting "		       "with 1 or 5\n");	}	len = WVAL(p, 1);	p += 3;	if (fs)		memcpy_tofs(data, p, len);	else		memcpy(data, p, len);	*data_len = len;	return p + len;}static byte *smb_name_mangle(byte * p, const byte * name){	int len, pad = 0;	len = strlen(name);	if (len < 16)		pad = 16 - len;	*p++ = 2 * (len + pad);	while (*name)	{		*p++ = (*name >> 4) + 'A';		*p++ = (*name & 0x0F) + 'A';		name++;	}	while (pad--)	{		*p++ = 'C';		*p++ = 'A';	}	*p++ = '\0';	return p;}/* The following are taken directly from msdos-fs *//* Linear day numbers of the respective 1sts in non-leap years. */static int day_n[] ={0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0};		  /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */extern struct timezone sys_tz;static intutc2local(int time){	return time - sys_tz.tz_minuteswest * 60;}static intlocal2utc(int time){	return time + sys_tz.tz_minuteswest * 60;}/* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */static intdate_dos2unix(unsigned short time, unsigned short date){	int month, year, secs;	month = ((date >> 5) & 15) - 1;	year = date >> 9;	secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 *	    ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 &&						   month < 2 ? 1 : 0) + 3653);	/* days since 1.1.70 plus 80's leap day */	return local2utc(secs);}/*****************************************************************************//*                                                                           *//*  Support section.                                                         *//*                                                                           *//*****************************************************************************/dwordsmb_len(byte * p){	return ((BVAL(p, 1) & 0x1) << 16L) | (BVAL(p, 2) << 8L) | (BVAL(p, 3));}static wordsmb_bcc(byte * packet){	int pos = SMB_HEADER_LEN + SMB_WCT(packet) * sizeof(word);	return WVAL(packet, pos);}/* smb_valid_packet: We check if packet fulfills the basic   requirements of a smb packet */static intsmb_valid_packet(byte * packet){	DDPRINTK("len: %d, wct: %d, bcc: %d\n",		 smb_len(packet), SMB_WCT(packet), SMB_BCC(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(byte * packet, int command, int wct, int bcc){	return (SMB_CMD(packet) == command &&		SMB_WCT(packet) >= wct &&		(bcc == -1 || SMB_BCC(packet) >= bcc)) ? 0 : -EIO;}static intsmb_errno(int errcls, int error){	if (errcls == ERRDOS)		switch (error)		{		case ERRbadfunc:			return EINVAL;		case ERRbadfile:			return ENOENT;		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:			return EREMOTEIO;		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 0;		case ERRbadshare:			return ETXTBSY;		case ERRlock:			return EDEADLK;		case ERRfilexists:			return EEXIST;		case 87:			return 0;	/* Unknown error!! */			/* This next error seems to occur on an mv when			 * the destination exists */		case 183:			return EEXIST;		default:			return EIO;	} else if (errcls == ERRSRV)		switch (error)		{		case ERRerror:			return ENFILE;		case ERRbadpw:			return EINVAL;		case ERRbadtype:			return EIO;		case ERRaccess:			return EACCES;		default:			return EIO;	} else if (errcls == ERRHRD)		switch (error)		{		case ERRnowrite:			return EROFS;		case ERRbadunit:			return ENODEV;		case ERRnotready:			return EUCLEAN;		case ERRbadcmd:			return EIO;		case ERRdata:			return EIO;		case ERRbadreq:			return ERANGE;		case ERRbadshare:			return ETXTBSY;		case ERRlock:			return EDEADLK;		default:			return EIO;	} else if (errcls == ERRCMD)		return EIO;	return 0;}static voidsmb_lock_server(struct smb_server *server){	while (server->lock)		sleep_on(&server->wait);	server->lock = 1;}static voidsmb_unlock_server(struct smb_server *server){	if (server->lock != 1)	{		printk("smb_unlock_server: was not locked!\n");	}	server->lock = 0;	wake_up(&server->wait);}/* 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_server *s, int command, int wct, int bcc){	int result = 0;	s->rcls = 0;	s->err = 0;	if (smb_request(s) < 0)	{		DPRINTK("smb_request failed\n");		result = -EIO;	} else if (smb_valid_packet(s->packet) != 0)	{		DPRINTK("not a valid packet!\n");		result = -EIO;	} else if (s->rcls != 0)	{		result = -smb_errno(s->rcls, s->err);	} else if (smb_verify(s->packet, command, wct, bcc) != 0)	{		DPRINTK("smb_verify failed\n");		result = -EIO;	}	return result;}/* smb_retry: This function should be called when smb_request_ok has   indicated an error. If the error was indicated because the   connection was killed, we try to reconnect. If smb_retry returns 0,   the error was indicated for another reason, so a retry would not be   of any use. */static intsmb_retry(struct smb_server *server){	if (server->state != CONN_INVALID)	{		return 0;	}	if (smb_release(server) < 0)	{		DPRINTK("smb_retry: smb_release failed\n");		server->state = CONN_RETRIED;		return 0;	}	if (smb_proc_reconnect(server) < 0)	{		DPRINTK("smb_proc_reconnect failed\n");		server->state = CONN_RETRIED;		return 0;	}	server->state = CONN_VALID;	return 1;}static intsmb_request_ok_unlock(struct smb_server *s, int command, int wct, int bcc){	int result = smb_request_ok(s, command, wct, bcc);	smb_unlock_server(s);	return result;}/* smb_setup_header: We completely set up the packet. You only have to   insert the command-specific fields */__u8 *smb_setup_header(struct smb_server * server, byte command, word wct, word bcc){	dword xmit_len = SMB_HEADER_LEN + wct * sizeof(word) + bcc + 2;	byte *p = server->packet;	byte *buf = server->packet;	p = smb_encode_smb_length(p, xmit_len - 4);	BSET(p, 0, 0xff);	BSET(p, 1, 'S');	BSET(p, 2, 'M');	BSET(p, 3, 'B');	BSET(p, 4, command);	p += 5;	memset(p, '\0', 19);	p += 19;	p += 8;	WSET(buf, smb_tid, server->tid);	WSET(buf, smb_pid, server->pid);	WSET(buf, smb_uid, server->server_uid);	WSET(buf, smb_mid, server->mid);	if (server->protocol > PROTOCOL_CORE)	{		BSET(buf, smb_flg, 0x8);		WSET(buf, smb_flg2, 0x3);	}	*p++ = wct;		/* wct */	p += 2 * wct;	WSET(p, 0, bcc);	return p + 2;}/* smb_setup_header_exclusive waits on server->lock and locks the   server, when it's free. You have to unlock it manually when you're   finished with server->packet! */static byte *smb_setup_header_exclusive(struct smb_server *server,			   byte command, word wct, word bcc){	smb_lock_server(server);	return smb_setup_header(server, command, wct, bcc);}static voidsmb_setup_bcc(struct smb_server *server, byte * p){	__u8 *packet = server->packet;	__u8 *pbcc = packet + SMB_HEADER_LEN + 2 * SMB_WCT(packet);	__u16 bcc = p - (pbcc + 2);	WSET(pbcc, 0, bcc);	smb_encode_smb_length(packet,			      SMB_HEADER_LEN + 2 * SMB_WCT(packet) - 2 + bcc);}/*****************************************************************************//*                                                                           *//*  File operation section.                                                  *//*                                                                           *//*****************************************************************************/intsmb_proc_open(struct smb_server *server,	      struct smb_inode_info *dir, const char *name, int len,	      struct smb_dirent *entry){	int error;	char *p;	char *buf;	const word o_attr = aSYSTEM | aHIDDEN | aDIR;	DPRINTK("smb_proc_open: name=%s\n", name);	smb_lock_server(server);	if (entry->opened != 0)	{		/* Somebody else opened the file while we slept */		smb_unlock_server(server);		return 0;	}      retry:	buf = server->packet;	p = smb_setup_header(server, SMBopen, 2, 0);	WSET(buf, smb_vwv0, 0x42);	/* read/write */	WSET(buf, smb_vwv1, o_attr);	*p++ = 4;	p = smb_encode_path(server, p, dir, name, len);	smb_setup_bcc(server, p);	if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0)	{		if (smb_retry(server))		{			goto retry;		}		if ((error != -EACCES) && (error != -ETXTBSY)		    && (error != -EROFS))		{			smb_unlock_server(server);			return error;		}		/* N.B. Packet may change after request */		buf = server->packet;		p = smb_setup_header(server, SMBopen, 2, 0);		WSET(buf, smb_vwv0, 0x40);	/* read only */		WSET(buf, smb_vwv1, o_attr);		*p++ = 4;		p = smb_encode_path(server, p, dir, name, len);		smb_setup_bcc(server, p);		if ((error = smb_request_ok(server, SMBopen, 7, 0)) != 0)		{			if (smb_retry(server))			{				goto retry;			}			smb_unlock_server(server);			return error;		}	}	/* We should now have data in vwv[0..6]. */	/* N.B. Packet may change after request */	buf = server->packet;	entry->fileid = WVAL(buf, smb_vwv0);	entry->attr = WVAL(buf, smb_vwv1);	entry->f_ctime = entry->f_atime =	    entry->f_mtime = local2utc(DVAL(buf, smb_vwv2));	entry->f_size = DVAL(buf, smb_vwv4);	entry->access = WVAL(buf, smb_vwv6);	entry->opened = 1;	entry->access &= 3;	smb_unlock_server(server);	DPRINTK("smb_proc_open: entry->access = %d\n", entry->access);	return 0;}intsmb_proc_close(struct smb_server *server,	       __u16 fileid, __u32 mtime){	char *buf;	smb_setup_header_exclusive(server, SMBclose, 3, 0);	buf = server->packet;	WSET(buf, smb_vwv0, fileid);	DSET(buf, smb_vwv1, utc2local(mtime));	return smb_request_ok_unlock(server, SMBclose, 0, 0);}/* In smb_proc_read and smb_proc_write we do not retry, because the   file-id would not be valid after a reconnection. *//* smb_proc_read: fs indicates if it should be copied with   memcpy_tofs. */intsmb_proc_read(struct smb_server *server, struct smb_dirent *finfo,	      off_t offset, long count, char *data, int fs){	word returned_count, data_len;	char *buf;	int error;

⌨️ 快捷键说明

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