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
- Lines: 314
- Date:
Fri Dec 19 15:24:21 1997
- Orig file:
v2.1.73/linux/fs/ntfs/support.c
- Orig date:
Wed Dec 31 16:00:00 1969
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