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 22static char print_buf[1024]; 23 24#ifdef DEBUG 25#include "sysctl.h" 26#include <linux/kernel.h> 27 28/* Debugging output */ 29void 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 */ 45void *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() */ 58void 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 67void *ntfs_malloc(int size) 68{ 69 return kmalloc(size, GFP_KERNEL); 70} 71#endif 72 73#ifndef ntfs_free 74void ntfs_free(void *block) 75{ 76 kfree(block); 77} 78#endif 79#endif /* DEBUG */ 80 81void 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 89void ntfs_memcpy(void *dest, const void *src, ntfs_size_t n) 90{ 91 memcpy(dest, src, n); 92} 93 94void 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. */ 100void 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 111int 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 printk(KERN_WARNING "NTFS: Invalid MFT record for 0x%x\n", mftno); 148 return -EIO; 149 } 150 ntfs_debug(DEBUG_OTHER, "read_mft_record: Done 0x%x\n", mftno); 151 return 0; 152} 153 154int ntfs_getput_clusters(ntfs_volume *vol, int cluster, ntfs_size_t start_offs, 155 ntfs_io *buf) 156{ 157 struct super_block *sb = NTFS_SB(vol); 158 struct buffer_head *bh; 159 int length = buf->size; 160 int error = 0; 161 ntfs_size_t to_copy; 162 163 ntfs_debug(DEBUG_OTHER, "%s_clusters %d %d %d\n", 164 buf->do_read ? "get" : "put", cluster, start_offs, length); 165 to_copy = vol->cluster_size - start_offs; 166 while (length) { 167 if (!(bh = sb_bread(sb, cluster))) { 168 ntfs_debug(DEBUG_OTHER, "%s failed\n", 169 buf->do_read ? "Reading" : "Writing"); 170 error = -EIO; 171 goto error_ret; 172 } 173 if (to_copy > length) 174 to_copy = length; 175 lock_buffer(bh); 176 if (buf->do_read) { 177 buf->fn_put(buf, bh->b_data + start_offs, to_copy); 178 unlock_buffer(bh); 179 } else { 180 buf->fn_get(bh->b_data + start_offs, buf, to_copy); 181 mark_buffer_dirty(bh); 182 unlock_buffer(bh); 183 /* 184 * Note: We treat synchronous IO on a per volume basis 185 * disregarding flags of individual inodes. This can 186 * lead to some strange write ordering effects upon a 187 * remount with a change in the sync flag but it should 188 * not break anything. [Except if the system crashes 189 * at that point in time but there would be more thigs 190 * to worry about than that in that case...]. (AIA) 191 */ 192 if (sb->s_flags & MS_SYNCHRONOUS) { 193 ll_rw_block(WRITE, 1, &bh); 194 wait_on_buffer(bh); 195 if (buffer_req(bh) && !buffer_uptodate(bh)) { 196 printk(KERN_ERR "IO error syncing NTFS " 197 "cluster [%s:%i]\n", 198 bdevname(sb->s_dev), cluster); 199 brelse(bh); 200 error = -EIO; 201 goto error_ret; 202 } 203 } 204 } 205 brelse(bh); 206 length -= to_copy; 207 start_offs = 0; 208 to_copy = vol->cluster_size; 209 cluster++; 210 } 211error_ret: 212 return error; 213} 214 215ntfs_time64_t ntfs_now(void) 216{ 217 return ntfs_unixutc2ntutc(CURRENT_TIME); 218} 219 220int ntfs_dupuni2map(ntfs_volume *vol, ntfs_u16 *in, int in_len, char **out, 221 int *out_len) 222{ 223 int i, o, chl, chi; 224 char *result, *buf, charbuf[NLS_MAX_CHARSET_SIZE]; 225 struct nls_table *nls = vol->nls_map; 226 227 result = ntfs_malloc(in_len + 1); 228 if (!result) 229 return -ENOMEM; 230 *out_len = in_len; 231 for (i = o = 0; i < in_len; i++) { 232 wchar_t uni = in[i]; 233 if ((chl = nls->uni2char(uni, charbuf, 234 NLS_MAX_CHARSET_SIZE)) > 0) { 235 /* Adjust result buffer. */ 236 if (chl > 1) { 237 buf = ntfs_malloc(*out_len + chl - 1); 238 if (!buf) { 239 i = -ENOMEM; 240 goto err_ret; 241 } 242 memcpy(buf, result, o); 243 ntfs_free(result); 244 result = buf; 245 *out_len += (chl - 1); 246 } 247 for (chi = 0; chi < chl; chi++) 248 result[o++] = charbuf[chi]; 249 } else { 250 /* Invalid character. */ 251 printk(KERN_ERR "NTFS: Unicode name contains a " 252 "character that cannot be converted " 253 "to chosen character set. Remount " 254 "with utf8 encoding and this should " 255 "work.\n"); 256 i = -EILSEQ; 257 goto err_ret; 258 } 259 } 260 result[*out_len] = '\0'; 261 *out = result; 262 return 0; 263err_ret: 264 ntfs_free(result); 265 *out_len = 0; 266 *out = NULL; 267 return i; 268} 269 270int ntfs_dupmap2uni(ntfs_volume *vol, char* in, int in_len, ntfs_u16 **out, 271 int *out_len) 272{ 273 int i, o; 274 ntfs_u16 *result; 275 struct nls_table *nls = vol->nls_map; 276 277 *out = result = ntfs_malloc(2 * in_len); 278 if (!result) { 279 *out_len = 0; 280 return -ENOMEM; 281 } 282 *out_len = in_len; 283 for (i = o = 0; i < in_len; i++, o++) { 284 wchar_t uni; 285 int charlen; 286 287 charlen = nls->char2uni(&in[i], in_len - i, &uni); 288 if (charlen < 0) { 289 i = charlen; 290 goto err_ret; 291 } 292 *out_len -= charlen - 1; 293 i += charlen - 1; 294 result[o] = uni; 295 if (!result[o]) { 296 i = -EILSEQ; 297 goto err_ret; 298 } 299 } 300 return 0; 301err_ret: 302 printk(KERN_ERR "NTFS: Name contains a character that cannot be " 303 "converted to Unicode.\n"); 304 ntfs_free(result); 305 *out_len = 0; 306 *out = NULL; 307 return i; 308} 309 310