Linux 2.2.0
[davej-history.git] / fs / ntfs / support.c
blobe0b79c8deedb70e8077099d63386762ab90172b1
1 /*
2 * support.c
3 * Specific support functions
5 * Copyright (C) 1997 Martin von Löwis
6 * Copyright (C) 1997 Régis Duchesne
8 */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13 #include "ntfstypes.h"
14 #include "struct.h"
15 #include "support.h"
17 #include <stdarg.h>
18 #include <linux/slab.h>
19 #include <linux/locks.h>
20 #include <linux/nls.h>
21 #include "util.h"
22 #include "inode.h"
23 #include "macros.h"
25 static char print_buf[1024];
27 #ifdef DEBUG
28 #include "sysctl.h"
29 #include <linux/kernel.h>
31 /* Debugging output */
32 void ntfs_debug(int mask, const char *fmt, ...)
34 va_list ap;
36 /* Filter it with the debugging level required */
37 if(ntdebug & mask){
38 va_start(ap,fmt);
39 strcpy(print_buf, KERN_DEBUG);
40 vsprintf(print_buf + 3, fmt, ap);
41 printk(print_buf);
42 va_end(ap);
46 #ifndef ntfs_malloc
47 /* Verbose kmalloc */
48 void *ntfs_malloc(int size)
50 void *ret;
52 ret = kmalloc(size, GFP_KERNEL);
53 ntfs_debug(DEBUG_MALLOC, "Allocating %x at %p\n", size, ret);
55 return ret;
57 #endif
59 #ifndef ntfs_free
60 /* Verbose kfree() */
61 void ntfs_free(void *block)
63 ntfs_debug(DEBUG_MALLOC, "Freeing memory at %p\n", block);
64 kfree(block);
66 #endif
67 #else
68 void ntfs_debug(int mask, const char *fmt, ...)
72 #ifndef ntfs_malloc
73 void *ntfs_malloc(int size)
75 return kmalloc(size, GFP_KERNEL);
77 #endif
79 #ifndef ntfs_free
80 void ntfs_free(void *block)
82 kfree(block);
84 #endif
85 #endif /* DEBUG */
87 void ntfs_bzero(void *s, int n)
89 memset(s, 0, n);
92 /* These functions deliberately return no value. It is dest, anyway,
93 and not used anywhere in the NTFS code. */
95 void ntfs_memcpy(void *dest, const void *src, ntfs_size_t n)
97 memcpy(dest, src, n);
100 void ntfs_memmove(void *dest, const void *src, ntfs_size_t n)
102 memmove(dest, src, n);
105 /* Warn that an error occured. */
106 void ntfs_error(const char *fmt,...)
108 va_list ap;
110 va_start(ap, fmt);
111 strcpy(print_buf, KERN_ERR);
112 vsprintf(print_buf + 3, fmt, ap);
113 printk(print_buf);
114 va_end(ap);
117 int ntfs_read_mft_record(ntfs_volume *vol, int mftno, char *buf)
119 int error;
120 ntfs_io io;
122 ntfs_debug(DEBUG_OTHER, "read_mft_record %x\n",mftno);
123 if(mftno==FILE_MFT)
125 ntfs_memcpy(buf,vol->mft,vol->mft_recordsize);
126 return 0;
128 if(!vol->mft_ino)
130 printk("ntfs:something is terribly wrong here\n");
131 return ENODATA;
133 io.fn_put=ntfs_put;
134 io.fn_get=0;
135 io.param=buf;
136 io.size=vol->mft_recordsize;
137 error=ntfs_read_attr(vol->mft_ino,vol->at_data,NULL,
138 mftno*vol->mft_recordsize,&io);
139 if(error || (io.size!=vol->mft_recordsize))
141 ntfs_debug(DEBUG_OTHER, "read_mft_record: read %x failed (%d,%d,%d)\n",
142 mftno,error,io.size,vol->mft_recordsize);
143 return error?error:ENODATA;
145 ntfs_debug(DEBUG_OTHER, "read_mft_record: finished read %x\n",mftno);
146 if(!ntfs_check_mft_record(vol,buf))
148 printk("Invalid MFT record for %x\n",mftno);
149 return EINVAL;
151 ntfs_debug(DEBUG_OTHER, "read_mft_record: Done %x\n",mftno);
152 return 0;
155 int ntfs_getput_clusters(ntfs_volume *vol, int cluster, ntfs_size_t start_offs,
156 ntfs_io *buf)
158 struct super_block *sb=NTFS_SB(vol);
159 struct buffer_head *bh;
160 ntfs_size_t to_copy;
161 int length=buf->size;
162 if(buf->do_read)
163 ntfs_debug(DEBUG_OTHER, "get_clusters %d %d %d\n",cluster,start_offs,length);
164 else
165 ntfs_debug(DEBUG_OTHER, "put_clusters %d %d %d\n",cluster,start_offs,length);
166 while(length)
168 if(!(bh=bread(sb->s_dev,cluster,vol->clustersize)))
170 ntfs_debug(DEBUG_OTHER, "%s failed\n", buf->do_read?"Reading":"Writing");
171 return EIO;
173 to_copy=min(vol->clustersize-start_offs,length);
174 lock_buffer(bh);
175 if(buf->do_read)
176 buf->fn_put(buf,bh->b_data+start_offs,to_copy);
177 else
179 buf->fn_get(bh->b_data+start_offs,buf,to_copy);
180 mark_buffer_dirty(bh,1);
182 unlock_buffer(bh);
183 length-=to_copy;
184 start_offs=0;
185 cluster++;
186 brelse(bh);
188 return 0;
191 ntfs_time64_t ntfs_now(void)
193 return ntfs_unixutc2ntutc(CURRENT_TIME);
196 /* when printing unicode characters base64, use this table.
197 It is not strictly base64, but the Linux vfat encoding.
198 base64 has the disadvantage of using the slash.
200 static char uni2esc[64]=
201 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-";
203 static unsigned char
204 esc2uni(char c)
206 if(c<'0')return 255;
207 if(c<='9')return c-'0';
208 if(c<'A')return 255;
209 if(c<='Z')return c-'A'+10;
210 if(c<'a')return 255;
211 if(c<='z')return c-'a'+36;
212 if(c=='+')return 62;
213 if(c=='-')return 63;
214 return 255;
217 int ntfs_dupuni2map(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
218 int *out_len)
220 int i,o,val;
221 char *result,*buf;
222 struct nls_table* nls=vol->nls_map;
224 result=ntfs_malloc(in_len+1);
225 if(!result)return ENOMEM;
226 *out_len=in_len;
227 result[in_len]='\0';
228 for(i=o=0;i<in_len;i++){
229 int cl,ch;
230 unsigned char* uni_page;
231 /* FIXME: byte order */
232 cl=in[i] & 0xFF;
233 ch=(in[i] >> 8) & 0xFF;
234 if(!nls){
235 if(!ch){
236 result[o++]=cl;
237 continue;
239 }else{
240 uni_page=nls->page_uni2charset[ch];
241 if(uni_page && uni_page[cl]){
242 result[o++]=uni_page[cl];
243 continue;
246 if(!(vol->nct & nct_uni_xlate))goto inval;
247 /* realloc */
248 buf=ntfs_malloc(*out_len+3);
249 memcpy(buf,result,o);
250 ntfs_free(result);
251 result=buf;
252 *out_len+=3;
253 result[o++]=':';
254 if(vol->nct & nct_uni_xlate_vfat){
255 val=(cl<<8)+ch;
256 result[o+2]=uni2esc[val & 0x3f];
257 val>>=6;
258 result[o+1]=uni2esc[val & 0x3f];
259 val>>=6;
260 result[o]=uni2esc[val & 0x3f];
261 o+=3;
262 }else{
263 val=(ch<<8)+cl;
264 result[o++]=uni2esc[val & 0x3f];
265 val>>=6;
266 result[o++]=uni2esc[val & 0x3f];
267 val>>=6;
268 result[o++]=uni2esc[val & 0x3f];
271 *out=result;
272 return 0;
273 inval:
274 ntfs_free(result);
275 *out=0;
276 return EILSEQ;
279 int ntfs_dupmap2uni(ntfs_volume *vol, char* in, int in_len, ntfs_u16 **out,
280 int *out_len)
282 int i,o;
283 ntfs_u16* result;
284 struct nls_table* nls=vol->nls_map;
286 *out=result=ntfs_malloc(2*in_len);
287 if(!result)return ENOMEM;
288 *out_len=in_len;
289 for(i=o=0;i<in_len;i++,o++){
290 unsigned short cl,ch;
291 if(in[i]!=':' || (vol->nct & nct_uni_xlate)==0){
292 cl=nls->charset2uni[(unsigned char)in[i]].uni1;
293 ch=nls->charset2uni[(unsigned char)in[i]].uni2;
294 }else{
295 unsigned char c1,c2,c3;
296 *out_len-=3;
297 c1=esc2uni(in[++i]);
298 c2=esc2uni(in[++i]);
299 c3=esc2uni(in[++i]);
300 if(c1==255 || c2==255 || c3==255)
301 cl=ch=0;
302 else if(vol->nct & nct_uni_xlate_vfat){
303 cl = (c1 << 4) + (c2 >> 2);
304 ch = ((c2 & 0x3) << 6) + c3;
305 }else{
306 ch=(c3 << 4) + (c2 >> 2);
307 cl=((c2 & 0x3) << 6) + c1;
310 /* FIXME: byte order */
311 result[o] = (ch<<8) | cl;
312 if(!result[o]){
313 ntfs_free(result);
314 return EILSEQ;
317 return 0;
321 * Local variables:
322 * c-file-style: "linux"
323 * End: