patch-2.1.74 linux/fs/ntfs/support.c

Next file: linux/fs/ntfs/support.h
Previous file: linux/fs/ntfs/super.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.73/linux/fs/ntfs/support.c linux/fs/ntfs/support.c
@@ -0,0 +1,313 @@
+/*
+ *  support.c
+ *  Specific support functions
+ *
+ *  Copyright (C) 1997 Martin von Löwis
+ *  Copyright (C) 1997 Régis Duchesne
+ *
+ */
+
+#ifdef NTFS_IN_LINUX_KERNEL
+#include <linux/config.h>
+#endif
+#include "types.h"
+#include "struct.h"
+#include "support.h"
+
+#include <stdarg.h>
+#include <linux/slab.h>
+#include <linux/locks.h>
+#include <linux/nls.h>
+#include "util.h"
+#include "inode.h"
+#include "macros.h"
+
+static char print_buf[1024];
+
+#ifdef DEBUG
+#include "sysctl.h"
+#include <linux/kernel.h>
+
+/* Debugging output */
+void ntfs_debug(int mask, const char *fmt, ...)
+{
+	va_list ap;
+
+	/* Filter it with the debugging level required */
+	if(ntdebug & mask){
+		va_start(ap,fmt);
+		strcpy(print_buf, KERN_DEBUG);
+		vsprintf(print_buf + 3, fmt, ap);
+		printk(print_buf);
+		va_end(ap);
+	}
+}
+
+/* Verbose kmalloc */
+void *ntfs_malloc(int size)
+{
+	void *ret;
+
+	ret = kmalloc(size, GFP_KERNEL);
+	ntfs_debug(DEBUG_MALLOC, "Allocating %x at %p\n", size, ret);
+
+	return ret;
+}
+
+/* Verbose kfree() */
+void ntfs_free(void *block)
+{
+        ntfs_debug(DEBUG_MALLOC, "Freeing memory at %p\n", block);
+	kfree(block);
+}
+#else
+void ntfs_debug(int mask, const char *fmt, ...)
+{
+}
+
+void *ntfs_malloc(int size)
+{
+	return kmalloc(size, GFP_KERNEL);
+}
+
+void ntfs_free(void *block)
+{
+	kfree(block);
+}
+#endif /* DEBUG */
+
+void ntfs_bzero(void *s, int n)
+{
+	memset(s, 0, n);
+}
+
+void *ntfs_memcpy(void *dest, const void *src, ntfs_size_t n)
+{
+	return memcpy(dest, src, n);
+}
+
+void *ntfs_memmove(void *dest, const void *src, ntfs_size_t n)
+{
+	return memmove(dest, src, n);
+}
+
+/* Warn that an error occured */
+void ntfs_error(const char *fmt,...)
+{
+        va_list ap;
+
+        va_start(ap, fmt);
+        strcpy(print_buf, KERN_ERR);
+        vsprintf(print_buf + 3, fmt, ap);
+        printk(print_buf);
+        va_end(ap);
+}
+
+int ntfs_read_mft_record(ntfs_volume *vol, int mftno, char *buf)
+{
+	int error;
+	ntfs_io io;
+
+	ntfs_debug(DEBUG_OTHER, "read_mft_record %x\n",mftno);
+	if(mftno==FILE_MFT)
+	{
+		ntfs_memcpy(buf,vol->mft,vol->mft_recordsize);
+		return 0;
+	}
+	if(!vol->mft_ino)
+	{
+		printk("ntfs:something is terribly wrong here\n");
+		return ENODATA;
+	}
+ 	io.fn_put=ntfs_put;
+	io.fn_get=0;
+	io.param=buf;
+	io.size=vol->mft_recordsize;
+	error=ntfs_read_attr(vol->mft_ino,vol->at_data,NULL,
+			     mftno*vol->mft_recordsize,&io);
+	if(error || (io.size!=vol->mft_recordsize))
+	{
+		ntfs_debug(DEBUG_OTHER, "read_mft_record: read %x failed (%d,%d,%d)\n",
+			   mftno,error,io.size,vol->mft_recordsize);
+		return error?error:ENODATA;
+	}
+	ntfs_debug(DEBUG_OTHER, "read_mft_record: finished read %x\n",mftno);
+	if(!ntfs_check_mft_record(vol,buf))
+	{
+		printk("Invalid MFT record for %x\n",mftno);
+		return EINVAL;
+	}
+	ntfs_debug(DEBUG_OTHER, "read_mft_record: Done %x\n",mftno);
+	return 0;
+}
+
+int ntfs_getput_clusters(ntfs_volume *vol, int cluster,	ntfs_size_t start_offs,
+	 ntfs_io *buf)
+{
+	struct super_block *sb=NTFS_SB(vol);
+	struct buffer_head *bh;
+	ntfs_size_t to_copy;
+	int length=buf->size;
+	if(buf->do_read)
+		ntfs_debug(DEBUG_OTHER, "get_clusters %d %d %d\n",cluster,start_offs,length);
+	else
+		ntfs_debug(DEBUG_OTHER, "put_clusters %d %d %d\n",cluster,start_offs,length);
+	while(length)
+	{
+		if(!(bh=bread(sb->s_dev,cluster,vol->clustersize)))
+		{
+			ntfs_debug(DEBUG_OTHER, "%s failed\n", buf->do_read?"Reading":"Writing");
+			return EIO;
+		}
+		to_copy=min(vol->clustersize-start_offs,length);
+		lock_buffer(bh);
+		if(buf->do_read)
+			buf->fn_put(buf,bh->b_data+start_offs,to_copy);
+		else
+		{
+			buf->fn_get(bh->b_data+start_offs,buf,to_copy);
+			mark_buffer_dirty(bh,1);
+		}
+		unlock_buffer(bh);
+		length-=to_copy;
+		start_offs=0;
+		cluster++;
+		brelse(bh);
+	}
+	return 0;
+}
+
+ntfs_time64_t ntfs_now(void)
+{
+	return ntfs_unixutc2ntutc(CURRENT_TIME);
+}
+
+/* when printing unicode characters base64, use this table.
+   It is not strictly base64, but the Linux vfat encoding.
+   base64 has the disadvantage of using the slash.
+*/
+static char uni2esc[64]=
+  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-";
+
+static unsigned char
+esc2uni(char c)
+{
+	if(c<'0')return 255;
+	if(c<='9')return c-'0';
+	if(c<'A')return 255;
+	if(c<='Z')return c-'A'+10;
+	if(c<'a')return 255;
+	if(c<='z')return c-'a'+36;
+	if(c=='+')return 62;
+	if(c=='-')return 63;
+	return 255;
+}
+
+int ntfs_dupuni2map(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
+  int *out_len)
+{
+	int i,o,val;
+	char *result,*buf;
+	struct nls_table* nls=vol->nls_map;
+
+	result=ntfs_malloc(in_len+1);
+	if(!result)return ENOMEM;
+	*out_len=in_len;
+	result[in_len]='\0';
+	for(i=o=0;i<in_len;i++){
+		int cl,ch;
+		unsigned char* uni_page;
+		/* FIXME: byte order */
+		cl=in[i] & 0xFF;
+		ch=(in[i] >> 8) & 0xFF;
+		if(!nls){
+			if(!ch){
+				result[o++]=cl;
+				continue;
+			}
+		}else{
+			uni_page=nls->page_uni2charset[ch];
+			if(uni_page && uni_page[cl]){
+				result[o++]=uni_page[cl];
+				continue;
+			}
+		}
+		if(!(vol->nct & nct_uni_xlate))goto inval;
+		/* realloc */
+		buf=ntfs_malloc(*out_len+3);
+		memcpy(buf,result,o);
+		ntfs_free(result);
+		result=buf;
+		*out_len+=3;
+		result[o++]=':';
+		if(vol->nct & nct_uni_xlate_vfat){
+			val=(cl<<8)+ch;
+			result[o+2]=uni2esc[val & 0x3f];
+			val>>=6;
+			result[o+1]=uni2esc[val & 0x3f];
+			val>>=6;
+			result[o]=uni2esc[val & 0x3f];
+			o+=3;
+		}else{
+			val=(ch<<8)+cl;
+			result[o++]=uni2esc[val & 0x3f];
+			val>>=6;
+			result[o++]=uni2esc[val & 0x3f];
+			val>>=6;
+			result[o++]=uni2esc[val & 0x3f];
+		}
+	}
+	*out=result;
+	return 0;
+ inval:
+	ntfs_free(result);
+	*out=0;
+	return EILSEQ;
+}
+
+int ntfs_dupmap2uni(ntfs_volume *vol, char* in, int in_len, ntfs_u16 **out,
+  int *out_len)
+{
+	int i,o;
+	ntfs_u16* result;
+	struct nls_table* nls=vol->nls_map;
+
+	*out=result=ntfs_malloc(2*in_len);
+	if(!result)return ENOMEM;
+	*out_len=in_len;
+	for(i=o=0;i<in_len;i++,o++){
+		unsigned short cl,ch;
+		if(in[i]!=':' || (vol->nct & nct_uni_xlate)==0){
+			cl=nls->charset2uni[(unsigned char)in[i]].uni1;
+			ch=nls->charset2uni[(unsigned char)in[i]].uni2;
+		}else{
+			unsigned char c1,c2,c3;
+			*out_len-=3;
+			c1=esc2uni(in[++i]);
+			c2=esc2uni(in[++i]);
+			c3=esc2uni(in[++i]);
+			if(c1==255 || c2==255 || c3==255)
+				cl=ch=0;
+			else if(vol->nct & nct_uni_xlate_vfat){
+				cl = (c1 << 4) + (c2 >> 2);
+				ch = ((c2 & 0x3) << 6) + c3;
+			}else{
+				ch=(c3 << 4) + (c2 >> 2);
+				cl=((c2 & 0x3) << 6) + c1;
+			}
+		}			
+		/* FIXME: byte order */
+		result[o] = (ch<<8) | cl;
+		if(!result[o]){
+			ntfs_free(result);
+			return EILSEQ;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov