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");