1 /*
2 * support.c - Specific support functions
3 *
4 * Copyright (C) 1997 Martin von L�wis
5 * Copyright (C) 1997 R�gis Duchesne
6 * Copyright (C) 2001 Anton Altaparmakov (AIA)
7 */
8
9 #include "ntfstypes.h"
10 #include "struct.h"
11 #include "support.h"
12
13 #include <stdarg.h>
14 #include <linux/slab.h>
15 #include <linux/locks.h>
16 #include <linux/fs.h>
17 #include "util.h"
18 #include "inode.h"
19 #include "macros.h"
20 #include <linux/nls.h>
21
22 static char print_buf[1024];
23
24 #ifdef DEBUG
25 #include "sysctl.h"
26 #include <linux/kernel.h>
27
28 /* Debugging output */
ntfs_debug(int mask,const char * fmt,...)29 void ntfs_debug(int mask, const char *fmt, ...)
30 {
31 va_list ap;
32
33 /* Filter it with the debugging level required */
34 if (ntdebug & mask) {
35 va_start(ap,fmt);
36 strcpy(print_buf, KERN_DEBUG "NTFS: ");
37 vsprintf(print_buf + 9, fmt, ap);
38 printk(print_buf);
39 va_end(ap);
40 }
41 }
42
43 #ifndef ntfs_malloc
44 /* Verbose kmalloc */
ntfs_malloc(int size)45 void *ntfs_malloc(int size)
46 {
47 void *ret;
48
49 ret = kmalloc(size, GFP_KERNEL);
50 ntfs_debug(DEBUG_MALLOC, "Allocating %x at %p\n", size, ret);
51
52 return ret;
53 }
54 #endif
55
56 #ifndef ntfs_free
57 /* Verbose kfree() */
ntfs_free(void * block)58 void ntfs_free(void *block)
59 {
60 ntfs_debug(DEBUG_MALLOC, "Freeing memory at %p\n", block);
61 kfree(block);
62 }
63 #endif
64 #else /* End of DEBUG functions. Normal ones below... */
65
66 #ifndef ntfs_malloc
ntfs_malloc(int size)67 void *ntfs_malloc(int size)
68 {
69 return kmalloc(size, GFP_KERNEL);
70 }
71 #endif
72
73 #ifndef ntfs_free
ntfs_free(void * block)74 void ntfs_free(void *block)
75 {
76 kfree(block);
77 }
78 #endif
79 #endif /* DEBUG */
80
ntfs_bzero(void * s,int n)81 void ntfs_bzero(void *s, int n)
82 {
83 memset(s, 0, n);
84 }
85
86 /* These functions deliberately return no value. It is dest, anyway,
87 and not used anywhere in the NTFS code. */
88
ntfs_memcpy(void * dest,const void * src,ntfs_size_t n)89 void ntfs_memcpy(void *dest, const void *src, ntfs_size_t n)
90 {
91 memcpy(dest, src, n);
92 }
93
ntfs_memmove(void * dest,const void * src,ntfs_size_t n)94 void ntfs_memmove(void *dest, const void *src, ntfs_size_t n)
95 {
96 memmove(dest, src, n);
97 }
98
99 /* Warn that an error occurred. */
ntfs_error(const char * fmt,...)100 void ntfs_error(const char *fmt,...)
101 {
102 va_list ap;
103
104 va_start(ap, fmt);
105 strcpy(print_buf, KERN_ERR "NTFS: ");
106 vsprintf(print_buf + 9, fmt, ap);
107 printk(print_buf);
108 va_end(ap);
109 }
110
ntfs_read_mft_record(ntfs_volume * vol,int mftno,char * buf)111 int ntfs_read_mft_record(ntfs_volume *vol, int mftno, char *buf)
112 {
113 int error;
114 ntfs_io io;
115
116 ntfs_debug(DEBUG_OTHER, "read_mft_record 0x%x\n", mftno);
117 if (mftno == FILE_Mft)
118 {
119 ntfs_memcpy(buf, vol->mft, vol->mft_record_size);
120 return 0;
121 }
122 if (!vol->mft_ino)
123 {
124 printk(KERN_ERR "NTFS: mft_ino is NULL. Something is terribly "
125 "wrong here!\n");
126 return -ENODATA;
127 }
128 io.fn_put = ntfs_put;
129 io.fn_get = 0;
130 io.param = buf;
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;
144 }
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
151 * this way. (AIA) */
152 printk(KERN_WARNING "NTFS: Invalid MFT record for 0x%x\n", mftno);
153 return -EIO;
154 }
155 ntfs_debug(DEBUG_OTHER, "read_mft_record: Done 0x%x\n", mftno);
156 return 0;
157 }
158
ntfs_getput_clusters(ntfs_volume * vol,int cluster,ntfs_size_t start_offs,ntfs_io * buf)159 int ntfs_getput_clusters(ntfs_volume *vol, int cluster, ntfs_size_t start_offs,
160 ntfs_io *buf)
161 {
162 struct super_block *sb = NTFS_SB(vol);
163 struct buffer_head *bh;
164 int length = buf->size;
165 int error = 0;
166 ntfs_size_t to_copy;
167
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;
171 while (length) {
172 if (!(bh = sb_bread(sb, cluster))) {
173 ntfs_debug(DEBUG_OTHER, "%s failed\n",
174 buf->do_read ? "Reading" : "Writing");
175 error = -EIO;
176 goto error_ret;
177 }
178 if (to_copy > length)
179 to_copy = length;
180 lock_buffer(bh);
181 if (buf->do_read) {
182 buf->fn_put(buf, bh->b_data + start_offs, to_copy);
183 unlock_buffer(bh);
184 } else {
185 buf->fn_get(bh->b_data + start_offs, buf, to_copy);
186 mark_buffer_dirty(bh);
187 unlock_buffer(bh);
188 /*
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)
196 */
197 if (sb->s_flags & MS_SYNCHRONOUS) {
198 ll_rw_block(WRITE, 1, &bh);
199 wait_on_buffer(bh);
200 if (buffer_req(bh) && !buffer_uptodate(bh)) {
201 printk(KERN_ERR "IO error syncing NTFS "
202 "cluster [%s:%i]\n",
203 bdevname(sb->s_dev), cluster);
204 brelse(bh);
205 error = -EIO;
206 goto error_ret;
207 }
208 }
209 }
210 brelse(bh);
211 length -= to_copy;
212 start_offs = 0;
213 to_copy = vol->cluster_size;
214 cluster++;
215 }
216 error_ret:
217 return error;
218 }
219
ntfs_now(void)220 ntfs_time64_t ntfs_now(void)
221 {
222 return ntfs_unixutc2ntutc(CURRENT_TIME);
223 }
224
ntfs_dupuni2map(ntfs_volume * vol,ntfs_u16 * in,int in_len,char ** out,int * out_len)225 int ntfs_dupuni2map(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out,
226 int *out_len)
227 {
228 int i, o, chl, chi;
229 char *result, *buf, charbuf[NLS_MAX_CHARSET_SIZE];
230 struct nls_table *nls = vol->nls_map;
231
232 result = ntfs_malloc(in_len + 1);
233 if (!result)
234 return -ENOMEM;
235 *out_len = in_len;
236 for (i = o = 0; i < in_len; i++) {
237 /* FIXME: Byte order? */
238 wchar_t uni = in[i];
239 if ((chl = nls->uni2char(uni, charbuf,
240 NLS_MAX_CHARSET_SIZE)) > 0) {
241 /* Adjust result buffer. */
242 if (chl > 1) {
243 buf = ntfs_malloc(*out_len + chl);
244 if (!buf) {
245 i = -ENOMEM;
246 goto err_ret;
247 }
248 memcpy(buf, result, o);
249 ntfs_free(result);
250 result = buf;
251 *out_len += (chl - 1);
252 }
253 for (chi = 0; chi < chl; chi++)
254 result[o++] = charbuf[chi];
255 } else {
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 "
261 "work.\n");
262 i = -EILSEQ;
263 goto err_ret;
264 }
265 }
266 result[*out_len] = '\0';
267 *out = result;
268 return 0;
269 err_ret:
270 ntfs_free(result);
271 *out_len = 0;
272 *out = NULL;
273 return i;
274 }
275
ntfs_dupmap2uni(ntfs_volume * vol,char * in,int in_len,ntfs_u16 ** out,int * out_len)276 int ntfs_dupmap2uni(ntfs_volume *vol, char* in, int in_len, ntfs_u16 **out,
277 int *out_len)
278 {
279 int i, o;
280 ntfs_u16 *result;
281 struct nls_table *nls = vol->nls_map;
282
283 *out = result = ntfs_malloc(2 * in_len);
284 if (!result) {
285 *out_len = 0;
286 return -ENOMEM;
287 }
288 *out_len = in_len;
289 for (i = o = 0; i < in_len; i++, o++) {
290 wchar_t uni;
291 int charlen;
292
293 charlen = nls->char2uni(&in[i], in_len - i, &uni);
294 if (charlen < 0) {
295 i = charlen;
296 goto err_ret;
297 }
298 *out_len -= charlen - 1;
299 i += charlen - 1;
300 /* FIXME: Byte order? */
301 result[o] = uni;
302 if (!result[o]) {
303 i = -EILSEQ;
304 goto err_ret;
305 }
306 }
307 return 0;
308 err_ret:
309 printk(KERN_ERR "NTFS: Name contains a character that cannot be "
310 "converted to Unicode.\n");
311 ntfs_free(result);
312 *out_len = 0;
313 *out = NULL;
314 return i;
315 }
316
317