The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/ntfs/support.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 */
   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 */
   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() */
   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
   67 void *ntfs_malloc(int size)
   68 {
   69         return kmalloc(size, GFP_KERNEL);
   70 }
   71 #endif
   72 
   73 #ifndef ntfs_free
   74 void ntfs_free(void *block)
   75 {
   76         kfree(block);
   77 }
   78 #endif
   79 #endif /* DEBUG */
   80 
   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 
   89 void ntfs_memcpy(void *dest, const void *src, ntfs_size_t n)
   90 {
   91         memcpy(dest, src, n);
   92 }
   93 
   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. */
  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 
  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 
  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 
  220 ntfs_time64_t ntfs_now(void)
  221 {
  222         return ntfs_unixutc2ntutc(CURRENT_TIME);
  223 }
  224 
  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 - 1);
  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 
  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 

Cache object: d27c5794330dd1cb86ad9be930faec20


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.