2 * support.c - Specific support functions
4 * Copyright (C) 1997 Martin von Löwis
5 * Copyright (C) 1997 Régis Duchesne
6 * Copyright (C) 2001 Anton Altaparmakov (AIA)
14 #include <linux/slab.h>
15 #include <linux/locks.h>
20 #include <linux/nls.h>
22 static char print_buf
[1024];
26 #include <linux/kernel.h>
28 /* Debugging output */
29 void ntfs_debug(int mask
, const char *fmt
, ...)
33 /* Filter it with the debugging level required */
36 strcpy(print_buf
, KERN_DEBUG
"NTFS: ");
37 vsprintf(print_buf
+ 9, fmt
, ap
);
45 void *ntfs_malloc(int size
)
49 ret
= kmalloc(size
, GFP_KERNEL
);
50 ntfs_debug(DEBUG_MALLOC
, "Allocating %x at %p\n", size
, ret
);
58 void ntfs_free(void *block
)
60 ntfs_debug(DEBUG_MALLOC
, "Freeing memory at %p\n", block
);
64 #else /* End of DEBUG functions. Normal ones below... */
67 void *ntfs_malloc(int size
)
69 return kmalloc(size
, GFP_KERNEL
);
74 void ntfs_free(void *block
)
81 void ntfs_bzero(void *s
, int n
)
86 /* These functions deliberately return no value. It is dest, anyway,
87 and not used anywhere in the NTFS code. */
89 void ntfs_memcpy(void *dest
, const void *src
, ntfs_size_t n
)
94 void ntfs_memmove(void *dest
, const void *src
, ntfs_size_t n
)
96 memmove(dest
, src
, n
);
99 /* Warn that an error occurred. */
100 void ntfs_error(const char *fmt
,...)
105 strcpy(print_buf
, KERN_ERR
"NTFS: ");
106 vsprintf(print_buf
+ 9, fmt
, ap
);
111 int ntfs_read_mft_record(ntfs_volume
*vol
, int mftno
, char *buf
)
116 ntfs_debug(DEBUG_OTHER
, "read_mft_record 0x%x\n", mftno
);
117 if (mftno
== FILE_Mft
)
119 ntfs_memcpy(buf
, vol
->mft
, vol
->mft_record_size
);
124 printk(KERN_ERR
"NTFS: mft_ino is NULL. Something is terribly "
128 io
.fn_put
= ntfs_put
;
131 io
.size
= vol
->mft_record_size
;
132 ntfs_debug(DEBUG_OTHER
, "read_mft_record: calling ntfs_read_attr with: "
133 "mftno = 0x%x, vol->mft_record_size_bits = 0x%x, "
134 "mftno << vol->mft_record_size_bits = 0x%Lx\n", mftno
,
135 vol
->mft_record_size_bits
,
136 (__s64
)mftno
<< vol
->mft_record_size_bits
);
137 error
= ntfs_read_attr(vol
->mft_ino
, vol
->at_data
, NULL
,
138 (__s64
)mftno
<< vol
->mft_record_size_bits
, &io
);
139 if (error
|| (io
.size
!= vol
->mft_record_size
)) {
140 ntfs_debug(DEBUG_OTHER
, "read_mft_record: read 0x%x failed "
141 "(%d,%d,%d)\n", mftno
, error
, io
.size
,
142 vol
->mft_record_size
);
143 return error
? error
: -ENODATA
;
145 ntfs_debug(DEBUG_OTHER
, "read_mft_record: finished read 0x%x\n", mftno
);
146 if (!ntfs_check_mft_record(vol
, buf
)) {
147 /* FIXME: This is incomplete behaviour. We might be able to
148 * recover at this stage. ntfs_check_mft_record() is too
149 * conservative at aborting it's operations. It is OK for
150 * now as we just can't handle some on disk structures
152 printk(KERN_WARNING
"NTFS: Invalid MFT record for 0x%x\n", mftno
);
155 ntfs_debug(DEBUG_OTHER
, "read_mft_record: Done 0x%x\n", mftno
);
159 int ntfs_getput_clusters(ntfs_volume
*vol
, int cluster
, ntfs_size_t start_offs
,
162 struct super_block
*sb
= NTFS_SB(vol
);
163 struct buffer_head
*bh
;
164 int length
= buf
->size
;
168 ntfs_debug(DEBUG_OTHER
, "%s_clusters %d %d %d\n",
169 buf
->do_read
? "get" : "put", cluster
, start_offs
, length
);
170 to_copy
= vol
->cluster_size
- start_offs
;
172 if (!(bh
= sb_bread(sb
, cluster
))) {
173 ntfs_debug(DEBUG_OTHER
, "%s failed\n",
174 buf
->do_read
? "Reading" : "Writing");
178 if (to_copy
> length
)
182 buf
->fn_put(buf
, bh
->b_data
+ start_offs
, to_copy
);
185 buf
->fn_get(bh
->b_data
+ start_offs
, buf
, to_copy
);
186 mark_buffer_dirty(bh
);
189 * Note: We treat synchronous IO on a per volume basis
190 * disregarding flags of individual inodes. This can
191 * lead to some strange write ordering effects upon a
192 * remount with a change in the sync flag but it should
193 * not break anything. [Except if the system crashes
194 * at that point in time but there would be more thigs
195 * to worry about than that in that case...]. (AIA)
197 if (sb
->s_flags
& MS_SYNCHRONOUS
) {
198 ll_rw_block(WRITE
, 1, &bh
);
200 if (buffer_req(bh
) && !buffer_uptodate(bh
)) {
201 printk(KERN_ERR
"IO error syncing NTFS "
203 bdevname(sb
->s_dev
), cluster
);
213 to_copy
= vol
->cluster_size
;
220 ntfs_time64_t
ntfs_now(void)
222 return ntfs_unixutc2ntutc(CURRENT_TIME
);
225 int ntfs_dupuni2map(ntfs_volume
*vol
, ntfs_u16
*in
, int in_len
, char **out
,
229 char *result
, *buf
, charbuf
[NLS_MAX_CHARSET_SIZE
];
230 struct nls_table
*nls
= vol
->nls_map
;
232 result
= ntfs_malloc(in_len
+ 1);
236 for (i
= o
= 0; i
< in_len
; i
++) {
237 /* FIXME: Byte order? */
239 if ((chl
= nls
->uni2char(uni
, charbuf
,
240 NLS_MAX_CHARSET_SIZE
)) > 0) {
241 /* Adjust result buffer. */
243 buf
= ntfs_malloc(*out_len
+ chl
);
248 memcpy(buf
, result
, o
);
251 *out_len
+= (chl
- 1);
253 for (chi
= 0; chi
< chl
; chi
++)
254 result
[o
++] = charbuf
[chi
];
256 /* Invalid character. */
257 printk(KERN_ERR
"NTFS: Unicode name contains a "
258 "character that cannot be converted "
259 "to chosen character set. Remount "
260 "with utf8 encoding and this should "
266 result
[*out_len
] = '\0';
276 int ntfs_dupmap2uni(ntfs_volume
*vol
, char* in
, int in_len
, ntfs_u16
**out
,
281 struct nls_table
*nls
= vol
->nls_map
;
283 *out
= result
= ntfs_malloc(2 * in_len
);
289 for (i
= o
= 0; i
< in_len
; i
++, o
++) {
293 charlen
= nls
->char2uni(&in
[i
], in_len
- i
, &uni
);
298 *out_len
-= charlen
- 1;
300 /* FIXME: Byte order? */
309 printk(KERN_ERR
"NTFS: Name contains a character that cannot be "
310 "converted to Unicode.\n");