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/fs.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * fs.c - NTFS driver for Linux 2.4.x
    3  *
    4  * Legato Systems, Inc. (http://www.legato.com) have sponsored Anton
    5  * Altaparmakov to develop NTFS on Linux since June 2001.
    6  *
    7  * Copyright (C) 1995-1997, 1999 Martin von Lwis
    8  * Copyright (C) 1996 Richard Russon
    9  * Copyright (C) 1996-1997 Rgis Duchesne
   10  * Copyright (C) 2000-2001, Anton Altaparmakov (AIA)
   11  */
   12 
   13 #include <linux/config.h>
   14 #include <linux/errno.h>
   15 #include "ntfstypes.h"
   16 #include "struct.h"
   17 #include "util.h"
   18 #include "inode.h"
   19 #include "super.h"
   20 #include "dir.h"
   21 #include "support.h"
   22 #include "macros.h"
   23 #include "sysctl.h"
   24 #include "attr.h"
   25 #include <linux/module.h>
   26 #include <asm/uaccess.h>
   27 #include <linux/locks.h>
   28 #include <linux/init.h>
   29 #include <linux/smp_lock.h>
   30 #include <linux/blkdev.h>
   31 #include <asm/page.h>
   32 #include <linux/nls.h>
   33 #include <linux/ntfs_fs.h>
   34 
   35 /* Forward declarations. */
   36 static struct inode_operations ntfs_dir_inode_operations;
   37 static struct file_operations ntfs_dir_operations;
   38 
   39 #define ITEM_SIZE 2040
   40 
   41 /* Io functions to user space. */
   42 static void ntfs_putuser(ntfs_io* dest, void *src, ntfs_size_t len)
   43 {
   44         copy_to_user(dest->param, src, len);
   45         dest->param += len;
   46 }
   47 
   48 #ifdef CONFIG_NTFS_RW
   49 struct ntfs_getuser_update_vm_s {
   50         const char *user;
   51         struct inode *ino;
   52         loff_t off;
   53 };
   54 
   55 static void ntfs_getuser_update_vm(void *dest, ntfs_io *src, ntfs_size_t len)
   56 {
   57         struct ntfs_getuser_update_vm_s *p = src->param;
   58         
   59         copy_from_user(dest, p->user, len);
   60         p->user += len;
   61         p->off += len;
   62 }
   63 #endif
   64 
   65 /* loff_t is 64 bit signed, so is cool. */
   66 static ssize_t ntfs_read(struct file *filp, char *buf, size_t count,loff_t *off)
   67 {
   68         int error;
   69         ntfs_io io;
   70         ntfs_attribute *attr;
   71         ntfs_inode *ino = NTFS_LINO2NINO(filp->f_dentry->d_inode);
   72 
   73         /* Inode is not properly initialized. */
   74         if (!ino)
   75                 return -EINVAL;
   76         ntfs_debug(DEBUG_OTHER, "ntfs_read %x, %Lx, %x ->",
   77                    (unsigned)ino->i_number, (unsigned long long)*off,
   78                    (unsigned)count);
   79         attr = ntfs_find_attr(ino, ino->vol->at_data, NULL);
   80         /* Inode has no unnamed data attribute. */
   81         if (!attr) {
   82                 ntfs_debug(DEBUG_OTHER, "ntfs_read: $DATA not found!\n");
   83                 return -EINVAL;
   84         }
   85         if (attr->flags & ATTR_IS_ENCRYPTED)
   86                 return -EACCES;
   87         /* Read the data. */
   88         io.fn_put = ntfs_putuser;
   89         io.fn_get = 0;
   90         io.param = buf;
   91         io.size = count;
   92         error = ntfs_read_attr(ino, ino->vol->at_data, NULL, *off, &io);
   93         if (error && !io.size) {
   94                 ntfs_debug(DEBUG_OTHER, "ntfs_read: read_attr failed with "
   95                                 "error %i, io size %u.\n", error, io.size);
   96                 return error;
   97         }
   98         *off += io.size;
   99         ntfs_debug(DEBUG_OTHER, "ntfs_read: finished. read %u bytes.\n",
  100                                                                 io.size);
  101         return io.size;
  102 }
  103 
  104 #ifdef CONFIG_NTFS_RW
  105 static ssize_t ntfs_write(struct file *filp, const char *buf, size_t count,
  106                 loff_t *pos)
  107 {
  108         int err;
  109         struct inode *vfs_ino = filp->f_dentry->d_inode;
  110         ntfs_inode *ntfs_ino = NTFS_LINO2NINO(vfs_ino);
  111         ntfs_attribute *data;
  112         ntfs_io io;
  113         struct ntfs_getuser_update_vm_s param;
  114 
  115         if (!ntfs_ino)
  116                 return -EINVAL;
  117         ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Entering for inode 0x%lx, "
  118                         "*pos 0x%Lx, count 0x%x.\n", ntfs_ino->i_number, *pos,
  119                         count);
  120         /* Allows to lock fs ro at any time. */
  121         if (vfs_ino->i_sb->s_flags & MS_RDONLY)
  122                 return -EROFS;
  123         data = ntfs_find_attr(ntfs_ino, ntfs_ino->vol->at_data, NULL);
  124         if (!data)
  125                 return -EINVAL;
  126         /* Evaluating O_APPEND is the file system's job... */
  127         if (filp->f_flags & O_APPEND)
  128                 *pos = vfs_ino->i_size;
  129         if (!data->resident && *pos + count > data->allocated) {
  130                 err = ntfs_extend_attr(ntfs_ino, data, *pos + count);
  131                 if (err < 0)
  132                         return err;
  133         }
  134         param.user = buf;
  135         param.ino = vfs_ino;
  136         param.off = *pos;
  137         io.fn_put = 0;
  138         io.fn_get = ntfs_getuser_update_vm;
  139         io.param = &param;
  140         io.size = count;
  141         io.do_read = 0;
  142         err = ntfs_readwrite_attr(ntfs_ino, data, *pos, &io);
  143         ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Returning %i\n", -err);
  144         if (!err) {
  145                 *pos += io.size;
  146                 if (*pos > vfs_ino->i_size)
  147                         vfs_ino->i_size = *pos;
  148                 mark_inode_dirty(vfs_ino);
  149                 return io.size;
  150         }
  151         return err;
  152 }
  153 #endif
  154 
  155 struct ntfs_filldir {
  156         struct inode *dir;
  157         filldir_t filldir;
  158         unsigned int type;
  159         u32 ph, pl;
  160         void *dirent;
  161         char *name;
  162         int namelen;
  163         int ret_code;
  164 };
  165 
  166 static int ntfs_printcb(ntfs_u8 *entry, void *param)
  167 {
  168         unsigned long inum = NTFS_GETU64(entry) & 0xffffffffffff;
  169         struct ntfs_filldir *nf = param;
  170         u32 flags = NTFS_GETU32(entry + 0x48);
  171         char show_sys_files = 0;
  172         u8 name_len = NTFS_GETU8(entry + 0x50);
  173         u8 name_type = NTFS_GETU8(entry + 0x51);
  174         int err;
  175         unsigned file_type;
  176 
  177         switch (nf->type) {
  178         case ngt_dos:
  179                 /* Don't display long names. */
  180                 if (!(name_type & 2))
  181                         return 0;
  182                 break;
  183         case ngt_nt:
  184                 /* Don't display short-only names. */
  185                 if ((name_type & 3) == 2)
  186                         return 0;
  187                 break;
  188         case ngt_posix:
  189                 break;
  190         case ngt_full:
  191                 show_sys_files = 1;
  192                 break;
  193         default:
  194                 BUG();
  195         }
  196         err = ntfs_encodeuni(NTFS_INO2VOL(nf->dir), (ntfs_u16*)(entry + 0x52),
  197                         name_len, &nf->name, &nf->namelen);
  198         if (err) {
  199                 ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping "
  200                                 "unrepresentable file.\n");
  201                 err = 0;
  202                 goto err_ret;
  203         }
  204         if (!show_sys_files && inum < 0x10UL) {
  205                 ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping system "
  206                                 "file (%s).\n", nf->name);
  207                 err = 0;
  208                 goto err_ret;
  209         }
  210         /* Do not return ".", as this is faked. */
  211         if (nf->namelen == 1 && nf->name[0] == '.') {
  212                 ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping \".\"\n");
  213                 err = 0;
  214                 goto err_ret;
  215         }
  216         nf->name[nf->namelen] = 0;
  217         if (flags & 0x10000000) /* FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT */
  218                 file_type = DT_DIR;
  219         else
  220                 file_type = DT_REG;
  221         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling filldir for %s with "
  222                         "len %i, f_pos 0x%Lx, inode %lu, %s.\n",
  223                         nf->name, nf->namelen, (loff_t)(nf->ph << 16) | nf->pl,
  224                         inum, file_type == DT_DIR ? "DT_DIR" : "DT_REG");
  225         /*
  226          * Userspace side of filldir expects an off_t rather than an loff_t.
  227          * And it also doesn't like the most significant bit being set as it
  228          * then considers the value to be negative. Thus this implementation
  229          * limits the number of index records to 32766, which should be plenty.
  230          */
  231         err = nf->filldir(nf->dirent, nf->name, nf->namelen,
  232                         (loff_t)(nf->ph << 16) | nf->pl, inum, file_type);
  233         if (err)
  234                 nf->ret_code = err;
  235 err_ret:
  236         nf->namelen = 0;
  237         ntfs_free(nf->name);
  238         nf->name = NULL;
  239         return err;
  240 }
  241 
  242 /*
  243  * readdir returns '.', then '..', then the directory entries in sequence.
  244  * As the root directory contains an entry for itself, '.' is not emulated for
  245  * the root directory.
  246  */
  247 static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir)
  248 {
  249         struct inode *dir = filp->f_dentry->d_inode;
  250         int err;
  251         struct ntfs_filldir cb;
  252 
  253         cb.ret_code = 0;
  254         cb.pl = filp->f_pos & 0xffff;
  255         cb.ph = (filp->f_pos >> 16) & 0x7fff;
  256         filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  257         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Entering for inode %lu, "
  258                         "f_pos 0x%Lx, i_mode 0x%x, i_count %lu.\n", dir->i_ino,
  259                         filp->f_pos, (unsigned int)dir->i_mode,
  260                         atomic_read(&dir->i_count));
  261         if (!cb.ph) {
  262                 /* Start of directory. Emulate "." and "..". */
  263                 if (!cb.pl) {
  264                         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling "
  265                                     "filldir for . with len 1, f_pos 0x%Lx, "
  266                                     "inode %lu, DT_DIR.\n", filp->f_pos,
  267                                     dir->i_ino);
  268                         cb.ret_code = filldir(dirent, ".", 1, filp->f_pos,
  269                                     dir->i_ino, DT_DIR);
  270                         if (cb.ret_code)
  271                                 goto done;
  272                         cb.pl++;
  273                         filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  274                 }
  275                 if (cb.pl == (u32)1) {
  276                         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling "
  277                                     "filldir for .. with len 2, f_pos 0x%Lx, "
  278                                     "inode %lu, DT_DIR.\n", filp->f_pos,
  279                                     filp->f_dentry->d_parent->d_inode->i_ino);
  280                         cb.ret_code = filldir(dirent, "..", 2, filp->f_pos,
  281                                     filp->f_dentry->d_parent->d_inode->i_ino,
  282                                     DT_DIR);
  283                         if (cb.ret_code)
  284                                 goto done;
  285                         cb.pl++;
  286                         filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  287                 }
  288         } else if (cb.ph >= 0x7fff)
  289                 /* End of directory. */
  290                 goto done;
  291         cb.dir = dir;
  292         cb.filldir = filldir;
  293         cb.dirent = dirent;
  294         cb.type = NTFS_INO2VOL(dir)->ngt;
  295         do {
  296                 ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Looking for next "
  297                                 "file using ntfs_getdir_unsorted(), f_pos "
  298                                 "0x%Lx.\n", (loff_t)(cb.ph << 16) | cb.pl);
  299                 err = ntfs_getdir_unsorted(NTFS_LINO2NINO(dir), &cb.ph, &cb.pl,
  300                                 ntfs_printcb, &cb);
  301         } while (!err && !cb.ret_code && cb.ph < 0x7fff);
  302         filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
  303         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After ntfs_getdir_unsorted()"
  304                         " calls, f_pos 0x%Lx.\n", filp->f_pos);
  305         if (!err) {
  306 done:
  307 #ifdef DEBUG
  308                 if (!cb.ret_code)
  309                         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): EOD, f_pos "
  310                                         "0x%Lx, returning 0.\n", filp->f_pos);
  311                 else 
  312                         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): filldir "
  313                                         "returned %i, returning 0, f_pos "
  314                                         "0x%Lx.\n", cb.ret_code, filp->f_pos);
  315 #endif
  316                 return 0;
  317         }
  318         ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Returning %i, f_pos 0x%Lx.\n",
  319                         err, filp->f_pos);
  320         return err;
  321 }
  322 
  323 /* Copied from vfat driver. */
  324 static int simple_getbool(char *s, int *setval)
  325 {
  326         if (s) {
  327                 if (!strcmp(s, "1") || !strcmp(s, "yes") || !strcmp(s, "true"))
  328                         *setval = 1;
  329                 else if (!strcmp(s, "") || !strcmp(s, "no") ||
  330                                                         !strcmp(s, "false"))
  331                         *setval = 0;
  332                 else
  333                         return 0;
  334         } else
  335                 *setval = 1;
  336         return 1;
  337 }
  338 
  339 /*
  340  * This needs to be outside parse_options() otherwise a remount will reset
  341  * these unintentionally.
  342  */
  343 static void init_ntfs_super_block(ntfs_volume* vol)
  344 {
  345         vol->uid = vol->gid = 0;
  346         vol->umask = 0077;
  347         vol->ngt = ngt_nt;
  348         vol->nls_map = (void*)-1;
  349         vol->mft_zone_multiplier = -1;
  350 }
  351 
  352 /* Parse the (re)mount options. */
  353 static int parse_options(ntfs_volume *vol, char *opt)
  354 {
  355         char *value;            /* Defaults if not specified and !remount. */
  356         ntfs_uid_t uid = -1;    /* 0, root user only */
  357         ntfs_gid_t gid = -1;    /* 0, root user only */
  358         int umask = -1;         /* 0077, owner access only */
  359         unsigned int ngt = -1;  /* ngt_nt */
  360         void *nls_map = NULL;   /* Try to load the default NLS. */
  361         int use_utf8 = -1;      /* If no NLS specified and loading the default
  362                                    NLS failed use utf8. */
  363         int mft_zone_mul = -1;  /* 1 */
  364 
  365         if (!opt)
  366                 goto done;
  367         for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) {
  368                 if ((value = strchr(opt, '=')) != NULL)
  369                         *value ++= '\0';
  370                 if (strcmp(opt, "uid") == 0) {
  371                         if (!value || !*value)
  372                                 goto needs_arg;
  373                         uid = simple_strtoul(value, &value, 0);
  374                         if (*value) {
  375                                 printk(KERN_ERR "NTFS: uid invalid argument\n");
  376                                 return 0;
  377                         }
  378                 } else if (strcmp(opt, "gid") == 0) {
  379                         if (!value || !*value)
  380                                 goto needs_arg;
  381                         gid = simple_strtoul(value, &value, 0);
  382                         if (*value) {
  383                                 printk(KERN_ERR "NTFS: gid invalid argument\n");
  384                                 return 0;
  385                         }
  386                 } else if (strcmp(opt, "umask") == 0) {
  387                         if (!value || !*value)
  388                                 goto needs_arg;
  389                         umask = simple_strtoul(value, &value, 0);
  390                         if (*value) {
  391                                 printk(KERN_ERR "NTFS: umask invalid "
  392                                                 "argument\n");
  393                                 return 0;
  394                         }
  395                 } else if (strcmp(opt, "mft_zone_multiplier") == 0) {
  396                         unsigned long ul;
  397 
  398                         if (!value || !*value)
  399                                 goto needs_arg;
  400                         ul = simple_strtoul(value, &value, 0);
  401                         if (*value) {
  402                                 printk(KERN_ERR "NTFS: mft_zone_multiplier "
  403                                                 "invalid argument\n");
  404                                 return 0;
  405                         }
  406                         if (ul >= 1 && ul <= 4)
  407                                 mft_zone_mul = ul;
  408                         else {
  409                                 mft_zone_mul = 1;
  410                                 printk(KERN_WARNING "NTFS: mft_zone_multiplier "
  411                                               "out of range. Setting to 1.\n");
  412                         }
  413                 } else if (strcmp(opt, "posix") == 0) {
  414                         int val;
  415                         if (!value || !*value)
  416                                 goto needs_arg;
  417                         if (!simple_getbool(value, &val))
  418                                 goto needs_bool;
  419                         ngt = val ? ngt_posix : ngt_nt;
  420                 } else if (strcmp(opt, "show_sys_files") == 0) {
  421                         int val = 0;
  422                         if (!value || !*value)
  423                                 val = 1;
  424                         else if (!simple_getbool(value, &val))
  425                                 goto needs_bool;
  426                         ngt = val ? ngt_full : ngt_nt;
  427                 } else if (strcmp(opt, "iocharset") == 0) {
  428                         if (!value || !*value)
  429                                 goto needs_arg;
  430                         nls_map = load_nls(value);
  431                         if (!nls_map) {
  432                                 printk(KERN_ERR "NTFS: charset not found");
  433                                 return 0;
  434                         }
  435                 } else if (strcmp(opt, "utf8") == 0) {
  436                         int val = 0;
  437                         if (!value || !*value)
  438                                 val = 1;
  439                         else if (!simple_getbool(value, &val))
  440                                 goto needs_bool;
  441                         use_utf8 = val;
  442                 } else {
  443                         printk(KERN_ERR "NTFS: unkown option '%s'\n", opt);
  444                         return 0;
  445                 }
  446         }
  447 done:
  448         if (use_utf8 == -1) {
  449                 /* utf8 was not specified at all. */
  450                 if (!nls_map) {
  451                         /*
  452                          * No NLS was specified. If first mount, load the
  453                          * default NLS, otherwise don't change the NLS setting.
  454                          */
  455                         if (vol->nls_map == (void*)-1)
  456                                 vol->nls_map = load_nls_default();
  457                 } else {
  458                         /* If an NLS was already loaded, unload it first. */
  459                         if (vol->nls_map && vol->nls_map != (void*)-1)
  460                                 unload_nls(vol->nls_map);
  461                         /* Use the specified NLS. */
  462                         vol->nls_map = nls_map;
  463                 }
  464         } else {
  465                 /* utf8 was specified. */
  466                 if (use_utf8 && nls_map) {
  467                         unload_nls(nls_map);
  468                         printk(KERN_ERR "NTFS: utf8 cannot be combined with "
  469                                         "iocharset.\n");
  470                         return 0;
  471                 }
  472                 /* If an NLS was already loaded, unload it first. */
  473                 if (vol->nls_map && vol->nls_map != (void*)-1)
  474                         unload_nls(vol->nls_map);
  475                 if (!use_utf8) {
  476                         /* utf8 was specified as false. */
  477                         if (!nls_map)
  478                                 /* No NLS was specified, load the default. */
  479                                 vol->nls_map = load_nls_default();
  480                         else
  481                                 /* Use the specified NLS. */
  482                                 vol->nls_map = nls_map;
  483                 } else
  484                         /* utf8 was specified as true. */
  485                         vol->nls_map = NULL;
  486         }
  487         if (uid != -1)
  488                 vol->uid = uid;
  489         if (gid != -1)
  490                 vol->gid = gid;
  491         if (umask != -1)
  492                 vol->umask = (ntmode_t)umask;
  493         if (ngt != -1)
  494                 vol->ngt = ngt;
  495         if (mft_zone_mul != -1) {
  496                 /* mft_zone_multiplier was specified. */
  497                 if (vol->mft_zone_multiplier != -1) {
  498                         /* This is a remount, ignore a change and warn user. */
  499                         if (vol->mft_zone_multiplier != mft_zone_mul)
  500                                 printk(KERN_WARNING "NTFS: Ignoring changes in "
  501                                                 "mft_zone_multiplier on "
  502                                                 "remount. If you want to "
  503                                                 "change this you need to "
  504                                                 "umount and mount again.\n");
  505                 } else
  506                         /* Use the specified multiplier. */
  507                         vol->mft_zone_multiplier = mft_zone_mul;
  508         } else if (vol->mft_zone_multiplier == -1)
  509                 /* No multiplier specified and first mount, so set default. */
  510                 vol->mft_zone_multiplier = 1;
  511         return 1;
  512 needs_arg:
  513         printk(KERN_ERR "NTFS: %s needs an argument", opt);
  514         return 0;
  515 needs_bool:
  516         printk(KERN_ERR "NTFS: %s needs boolean argument", opt);
  517         return 0;
  518 }
  519                         
  520 static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *d)
  521 {
  522         struct inode *res = 0;
  523         char *item = 0;
  524         ntfs_iterate_s walk;
  525         int err;
  526         
  527         ntfs_debug(DEBUG_NAME1, __FUNCTION__ "(): Looking up %s in directory "
  528                         "ino 0x%x.\n", d->d_name.name, (unsigned)dir->i_ino);
  529         walk.name = NULL;
  530         walk.namelen = 0;
  531         /* Convert to wide string. */
  532         err = ntfs_decodeuni(NTFS_INO2VOL(dir), (char*)d->d_name.name,
  533                                d->d_name.len, &walk.name, &walk.namelen);
  534         if (err)
  535                 goto err_ret;
  536         item = ntfs_malloc(ITEM_SIZE);
  537         if (!item) {
  538                 err = -ENOMEM;
  539                 goto err_ret;
  540         }
  541         /* ntfs_getdir will place the directory entry into item, and the first
  542          * long long is the MFT record number. */
  543         walk.type = BY_NAME;
  544         walk.dir = NTFS_LINO2NINO(dir);
  545         walk.result = item;
  546         if (ntfs_getdir_byname(&walk))
  547                 res = iget(dir->i_sb, NTFS_GETU32(item));
  548         d_add(d, res);
  549         ntfs_free(item);
  550         ntfs_free(walk.name);
  551         /* Always return success, the dcache will handle negative entries. */
  552         return NULL;
  553 err_ret:
  554         ntfs_free(walk.name);
  555         return ERR_PTR(err);
  556 }
  557 
  558 static struct file_operations ntfs_file_operations = {
  559         llseek:         generic_file_llseek,
  560         read:           ntfs_read,
  561 #ifdef CONFIG_NTFS_RW
  562         write:          ntfs_write,
  563 #endif
  564         open:           generic_file_open,
  565 };
  566 
  567 static struct inode_operations ntfs_inode_operations;
  568 
  569 #ifdef CONFIG_NTFS_RW
  570 static int ntfs_create(struct inode* dir, struct dentry *d, int mode)
  571 {
  572         struct inode *r = 0;
  573         ntfs_inode *ino = 0;
  574         ntfs_volume *vol;
  575         int error = 0;
  576         ntfs_attribute *si;
  577 
  578         r = new_inode(dir->i_sb);
  579         if (!r) {
  580                 error = -ENOMEM;
  581                 goto fail;
  582         }
  583         ntfs_debug(DEBUG_OTHER, "ntfs_create %s\n", d->d_name.name);
  584         vol = NTFS_INO2VOL(dir);
  585         ino = NTFS_LINO2NINO(r);
  586         error = ntfs_alloc_file(NTFS_LINO2NINO(dir), ino, (char*)d->d_name.name,
  587                                 d->d_name.len);
  588         if (error) {
  589                 ntfs_error("ntfs_alloc_file FAILED: error = %i", error);
  590                 goto fail;
  591         }
  592         /* Not doing this one was causing a huge amount of corruption! Now the
  593          * bugger bytes the dust! (-8 (AIA) */
  594         r->i_ino = ino->i_number;
  595         error = ntfs_update_inode(ino);
  596         if (error)
  597                 goto fail;
  598         error = ntfs_update_inode(NTFS_LINO2NINO(dir));
  599         if (error)
  600                 goto fail;
  601         r->i_uid = vol->uid;
  602         r->i_gid = vol->gid;
  603         /* FIXME: dirty? dev? */
  604         /* Get the file modification times from the standard information. */
  605         si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
  606         if (si) {
  607                 char *attr = si->d.data;
  608                 r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
  609                 r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
  610                 r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
  611         }
  612         /* It's not a directory */
  613         r->i_op = &ntfs_inode_operations;
  614         r->i_fop = &ntfs_file_operations;
  615         r->i_mode = S_IFREG | S_IRUGO;
  616 #ifdef CONFIG_NTFS_RW
  617         r->i_mode |= S_IWUGO;
  618 #endif
  619         r->i_mode &= ~vol->umask;
  620         insert_inode_hash(r);
  621         d_instantiate(d, r);
  622         return 0;
  623  fail:
  624         if (r)
  625                 iput(r);
  626         return error;
  627 }
  628 
  629 static int _linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode)
  630 {
  631         int error;
  632         struct inode *r = 0;
  633         ntfs_volume *vol;
  634         ntfs_inode *ino;
  635         ntfs_attribute *si;
  636 
  637         ntfs_debug (DEBUG_DIR1, "mkdir %s in %x\n", d->d_name.name, dir->i_ino);
  638         error = -ENAMETOOLONG;
  639         if (d->d_name.len > /* FIXME: */ 255)
  640                 goto out;
  641         error = -EIO;
  642         r = new_inode(dir->i_sb);
  643         if (!r)
  644                 goto out;
  645         vol = NTFS_INO2VOL(dir);
  646         ino = NTFS_LINO2NINO(r);
  647         error = ntfs_mkdir(NTFS_LINO2NINO(dir), d->d_name.name, d->d_name.len,
  648                            ino);
  649         if (error)
  650                 goto out;
  651         /* Not doing this one was causing a huge amount of corruption! Now the
  652          * bugger bytes the dust! (-8 (AIA) */
  653         r->i_ino = ino->i_number;
  654         r->i_uid = vol->uid;
  655         r->i_gid = vol->gid;
  656         si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
  657         if (si) {
  658                 char *attr = si->d.data;
  659                 r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
  660                 r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
  661                 r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
  662         }
  663         /* It's a directory. */
  664         r->i_op = &ntfs_dir_inode_operations;
  665         r->i_fop = &ntfs_dir_operations;
  666         r->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
  667 #ifdef CONFIG_NTFS_RW
  668         r->i_mode |= S_IWUGO;
  669 #endif
  670         r->i_mode &= ~vol->umask;       
  671         
  672         insert_inode_hash(r);
  673         d_instantiate(d, r);
  674         error = 0;
  675  out:
  676         ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", error);
  677         return error;
  678 }
  679 #endif
  680 
  681 static struct file_operations ntfs_dir_operations = {
  682         read:           generic_read_dir,
  683         readdir:        ntfs_readdir,
  684 };
  685 
  686 static struct inode_operations ntfs_dir_inode_operations = {
  687         lookup:         ntfs_lookup,
  688 #ifdef CONFIG_NTFS_RW
  689         create:         ntfs_create,
  690         mkdir:          _linux_ntfs_mkdir,
  691 #endif
  692 };
  693 
  694 /* ntfs_read_inode() is called by the Virtual File System (the kernel layer 
  695  * that deals with filesystems) when iget is called requesting an inode not
  696  * already present in the inode table. Typically filesystems have separate
  697  * inode_operations for directories, files and symlinks. */
  698 static void ntfs_read_inode(struct inode* inode)
  699 {
  700         ntfs_volume *vol;
  701         ntfs_inode *ino;
  702         ntfs_attribute *data;
  703         ntfs_attribute *si;
  704 
  705         vol = NTFS_INO2VOL(inode);
  706         inode->i_mode = 0;
  707         ntfs_debug(DEBUG_OTHER, "ntfs_read_inode 0x%lx\n", inode->i_ino);
  708         switch (inode->i_ino) {
  709                 /* Those are loaded special files. */
  710         case FILE_Mft:
  711                 if (!vol->mft_ino || ((vol->ino_flags & 1) == 0))
  712                         goto sys_file_error;
  713                 ntfs_memcpy(&inode->u.ntfs_i, vol->mft_ino, sizeof(ntfs_inode));
  714                 ino = vol->mft_ino;
  715                 vol->mft_ino = &inode->u.ntfs_i;
  716                 vol->ino_flags &= ~1;
  717                 ntfs_free(ino);
  718                 ino = vol->mft_ino;
  719                 ntfs_debug(DEBUG_OTHER, "Opening $MFT!\n");
  720                 break;
  721         case FILE_MftMirr:
  722                 if (!vol->mftmirr || ((vol->ino_flags & 2) == 0))
  723                         goto sys_file_error;
  724                 ntfs_memcpy(&inode->u.ntfs_i, vol->mftmirr, sizeof(ntfs_inode));
  725                 ino = vol->mftmirr;
  726                 vol->mftmirr = &inode->u.ntfs_i;
  727                 vol->ino_flags &= ~2;
  728                 ntfs_free(ino);
  729                 ino = vol->mftmirr;
  730                 ntfs_debug(DEBUG_OTHER, "Opening $MFTMirr!\n");
  731                 break;
  732         case FILE_BitMap:
  733                 if (!vol->bitmap || ((vol->ino_flags & 4) == 0))
  734                         goto sys_file_error;
  735                 ntfs_memcpy(&inode->u.ntfs_i, vol->bitmap, sizeof(ntfs_inode));
  736                 ino = vol->bitmap;
  737                 vol->bitmap = &inode->u.ntfs_i;
  738                 vol->ino_flags &= ~4;
  739                 ntfs_free(ino);
  740                 ino = vol->bitmap;
  741                 ntfs_debug(DEBUG_OTHER, "Opening $Bitmap!\n");
  742                 break;
  743         case FILE_LogFile ... FILE_AttrDef:
  744         /* No need to log root directory accesses. */
  745         case FILE_Boot ... FILE_UpCase:
  746                 ntfs_debug(DEBUG_OTHER, "Opening system file %i!\n",
  747                                 inode->i_ino);
  748         default:
  749                 ino = &inode->u.ntfs_i;
  750                 if (!ino || ntfs_init_inode(ino, NTFS_INO2VOL(inode),
  751                                                                 inode->i_ino))
  752                 {
  753                         ntfs_debug(DEBUG_OTHER, "NTFS: Error loading inode "
  754                                         "0x%x\n", (unsigned int)inode->i_ino);
  755                         return;
  756                 }
  757         }
  758         /* Set uid/gid from mount options */
  759         inode->i_uid = vol->uid;
  760         inode->i_gid = vol->gid;
  761         inode->i_nlink = 1;
  762         /* Use the size of the data attribute as file size */
  763         data = ntfs_find_attr(ino, vol->at_data, NULL);
  764         if (!data)
  765                 inode->i_size = 0;
  766         else
  767                 inode->i_size = data->size;
  768         /* Get the file modification times from the standard information. */
  769         si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
  770         if (si) {
  771                 char *attr = si->d.data;
  772                 inode->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
  773                 inode->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
  774                 inode->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
  775         }
  776         /* If it has an index root, it's a directory. */
  777         if (ntfs_find_attr(ino, vol->at_index_root, "$I30")) {
  778                 ntfs_attribute *at;
  779                 at = ntfs_find_attr(ino, vol->at_index_allocation, "$I30");
  780                 inode->i_size = at ? at->size : 0;
  781                 inode->i_op = &ntfs_dir_inode_operations;
  782                 inode->i_fop = &ntfs_dir_operations;
  783                 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
  784         } else {
  785                 inode->i_op = &ntfs_inode_operations;
  786                 inode->i_fop = &ntfs_file_operations;
  787                 inode->i_mode = S_IFREG | S_IRUGO;
  788         }
  789 #ifdef CONFIG_NTFS_RW
  790         if (!data || !(data->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED)))
  791                 inode->i_mode |= S_IWUGO;
  792 #endif
  793         inode->i_mode &= ~vol->umask;
  794         return;
  795 sys_file_error:
  796         ntfs_error("Critical error. Tried to call ntfs_read_inode() before we "
  797                 "have completed read_super() or VFS error.\n");
  798         // FIXME: Should we panic() at this stage?
  799 }
  800 
  801 #ifdef CONFIG_NTFS_RW
  802 static void ntfs_write_inode(struct inode *ino, int unused)
  803 {
  804         lock_kernel();
  805         ntfs_debug(DEBUG_LINUX, "ntfs_write_inode 0x%x\n", ino->i_ino);
  806         ntfs_update_inode(NTFS_LINO2NINO(ino));
  807         unlock_kernel();
  808 }
  809 #endif
  810 
  811 static void _ntfs_clear_inode(struct inode *inode)
  812 {
  813         ntfs_inode *ino;
  814         ntfs_volume *vol;
  815         
  816         lock_kernel();
  817         ntfs_debug(DEBUG_OTHER, "_ntfs_clear_inode 0x%x\n", inode->i_ino);
  818         vol = NTFS_INO2VOL(inode);
  819         if (!vol)
  820                 ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is "
  821                                 "NULL.\n");
  822         switch (inode->i_ino) {
  823         case FILE_Mft:
  824                 if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) {
  825                         ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
  826                         ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
  827                         vol->mft_ino = ino;
  828                         vol->ino_flags |= 1;
  829                         goto unl_out;
  830                 }
  831                 break;
  832         case FILE_MftMirr:
  833                 if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) {
  834                         ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
  835                         ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
  836                         vol->mftmirr = ino;
  837                         vol->ino_flags |= 2;
  838                         goto unl_out;
  839                 }
  840                 break;
  841         case FILE_BitMap:
  842                 if (vol->bitmap && ((vol->ino_flags & 4) == 0)) {
  843                         ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
  844                         ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
  845                         vol->bitmap = ino;
  846                         vol->ino_flags |= 4;
  847                         goto unl_out;
  848                 }
  849                 break;
  850         default:
  851                 /* Nothing. Just clear the inode and exit. */
  852         }
  853         ntfs_clear_inode(&inode->u.ntfs_i);
  854 unl_out:
  855         unlock_kernel();
  856         return;
  857 }
  858 
  859 /* Called when umounting a filesystem by do_umount() in fs/super.c. */
  860 static void ntfs_put_super(struct super_block *sb)
  861 {
  862         ntfs_volume *vol;
  863 
  864         ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");
  865         vol = NTFS_SB2VOL(sb);
  866         ntfs_release_volume(vol);
  867         if (vol->nls_map)
  868                 unload_nls(vol->nls_map);
  869         ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
  870 }
  871 
  872 /* Called by the kernel when asking for stats. */
  873 static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
  874 {
  875         struct inode *mft;
  876         ntfs_volume *vol;
  877         __s64 size;
  878         int error;
  879 
  880         ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
  881         vol = NTFS_SB2VOL(sb);
  882         sf->f_type = NTFS_SUPER_MAGIC;
  883         sf->f_bsize = vol->cluster_size;
  884         error = ntfs_get_volumesize(NTFS_SB2VOL(sb), &size);
  885         if (error)
  886                 return error;
  887         sf->f_blocks = size;    /* Volumesize is in clusters. */
  888         size = (__s64)ntfs_get_free_cluster_count(vol->bitmap);
  889         /* Just say zero if the call failed. */
  890         if (size < 0LL)
  891                 size = 0;
  892         sf->f_bfree = sf->f_bavail = size;
  893         ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling mft = iget(sb, "
  894                         "FILE_Mft)\n");
  895         mft = iget(sb, FILE_Mft);
  896         ntfs_debug(DEBUG_OTHER, "ntfs_statfs: iget(sb, FILE_Mft) returned "
  897                         "0x%x\n", mft);
  898         if (!mft)
  899                 return -EIO;
  900         sf->f_files = mft->i_size >> vol->mft_record_size_bits;
  901         ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling iput(mft)\n");
  902         iput(mft);
  903         /* Should be read from volume. */
  904         sf->f_namelen = 255;
  905         return 0;
  906 }
  907 
  908 /* Called when remounting a filesystem by do_remount_sb() in fs/super.c. */
  909 static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options)
  910 {
  911         if (!parse_options(NTFS_SB2VOL(sb), options))
  912                 return -EINVAL;
  913         return 0;
  914 }
  915 
  916 /* Define the super block operation that are implemented */
  917 static struct super_operations ntfs_super_operations = {
  918         read_inode:     ntfs_read_inode,
  919 #ifdef CONFIG_NTFS_RW
  920         write_inode:    ntfs_write_inode,
  921 #endif
  922         put_super:      ntfs_put_super,
  923         statfs:         ntfs_statfs,
  924         remount_fs:     ntfs_remount_fs,
  925         clear_inode:    _ntfs_clear_inode,
  926 };
  927 
  928 /**
  929  * is_boot_sector_ntfs - check an NTFS boot sector for validity
  930  * @b:          buffer containing bootsector to check
  931  * 
  932  * Check whether @b contains a valid NTFS boot sector.
  933  * Return 1 if @b is a valid NTFS bootsector or 0 if not.
  934  */
  935 static int is_boot_sector_ntfs(ntfs_u8 *b)
  936 {
  937         ntfs_u32 i;
  938 
  939         /* FIXME: We don't use checksumming yet as NT4(SP6a) doesn't either...
  940          * But we might as well have the code ready to do it. (AIA) */
  941 #if 0
  942         /* Calculate the checksum. */
  943         if (b < b + 0x50) {
  944                 ntfs_u32 *u;
  945                 ntfs_u32 *bi = (ntfs_u32 *)(b + 0x50);
  946                 
  947                 for (u = bi, i = 0; u < bi; ++u)
  948                         i += NTFS_GETU32(*u);
  949         }
  950 #endif
  951         /* Check magic is "NTFS    " */
  952         if (b[3] != 0x4e) goto not_ntfs;
  953         if (b[4] != 0x54) goto not_ntfs;
  954         if (b[5] != 0x46) goto not_ntfs;
  955         if (b[6] != 0x53) goto not_ntfs;
  956         for (i = 7; i < 0xb; ++i)
  957                 if (b[i] != 0x20) goto not_ntfs;
  958         /* Check bytes per sector value is between 512 and 4096. */
  959         if (b[0xb] != 0) goto not_ntfs;
  960         if (b[0xc] > 0x10) goto not_ntfs;
  961         /* Check sectors per cluster value is valid. */
  962         switch (b[0xd]) {
  963         case 1: case 2: case 4: case 8: case 16:
  964         case 32: case 64: case 128:
  965                 break;
  966         default:
  967                 goto not_ntfs;
  968         }
  969         /* Check reserved sectors value and four other fields are zero. */
  970         for (i = 0xe; i < 0x15; ++i) 
  971                 if (b[i] != 0) goto not_ntfs;
  972         if (b[0x16] != 0) goto not_ntfs;
  973         if (b[0x17] != 0) goto not_ntfs;
  974         for (i = 0x20; i < 0x24; ++i)
  975                 if (b[i] != 0) goto not_ntfs;
  976         /* Check clusters per file record segment value is valid. */
  977         if (b[0x40] < 0xe1 || b[0x40] > 0xf7) {
  978                 switch (b[0x40]) {
  979                 case 1: case 2: case 4: case 8: case 16: case 32: case 64:
  980                         break;
  981                 default:
  982                         goto not_ntfs;
  983                 }
  984         }
  985         /* Check clusters per index block value is valid. */
  986         if (b[0x44] < 0xe1 || b[0x44] > 0xf7) {
  987                 switch (b[0x44]) {
  988                 case 1: case 2: case 4: case 8: case 16: case 32: case 64:
  989                         break;
  990                 default:
  991                         goto not_ntfs;
  992                 }
  993         }
  994         return 1;
  995 not_ntfs:
  996         return 0;
  997 }
  998 
  999 /* Called to mount a filesystem by read_super() in fs/super.c.
 1000  * Return a super block, the main structure of a filesystem.
 1001  *
 1002  * NOTE : Don't store a pointer to an option, as the page containing the
 1003  * options is freed after ntfs_read_super() returns.
 1004  *
 1005  * NOTE : A context switch can happen in kernel code only if the code blocks
 1006  * (= calls schedule() in kernel/sched.c). */
 1007 struct super_block *ntfs_read_super(struct super_block *sb, void *options,
 1008                 int silent)
 1009 {
 1010         ntfs_volume *vol;
 1011         struct buffer_head *bh;
 1012         int i, to_read, blocksize;
 1013 
 1014         ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");
 1015         vol = NTFS_SB2VOL(sb);
 1016         init_ntfs_super_block(vol);
 1017         if (!parse_options(vol, (char*)options))
 1018                 goto ntfs_read_super_vol;
 1019         blocksize = get_hardsect_size(sb->s_dev);
 1020         if (blocksize < 512)
 1021                 blocksize = 512;
 1022         if (set_blocksize(sb->s_dev, blocksize) < 0) {
 1023                 ntfs_error("Unable to set blocksize %d.\n", blocksize);
 1024                 goto ntfs_read_super_vol;
 1025         }
 1026         sb->s_blocksize = blocksize;
 1027         /* Read the super block (boot block). */
 1028         if (!(bh = sb_bread(sb, 0))) {
 1029                 ntfs_error("Reading super block failed\n");
 1030                 goto ntfs_read_super_unl;
 1031         }
 1032         ntfs_debug(DEBUG_OTHER, "Done reading boot block\n");
 1033         /* Check for valid 'NTFS' boot sector. */
 1034         if (!is_boot_sector_ntfs(bh->b_data)) {
 1035                 ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n");
 1036                 bforget(bh);
 1037                 goto ntfs_read_super_unl;
 1038         }
 1039         ntfs_debug(DEBUG_OTHER, "Going to init volume\n");
 1040         if (ntfs_init_volume(vol, bh->b_data) < 0) {
 1041                 ntfs_debug(DEBUG_OTHER, "Init volume failed.\n");
 1042                 bforget(bh);
 1043                 goto ntfs_read_super_unl;
 1044         }
 1045         ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%lx\n", vol->mft_lcn);
 1046         brelse(bh);
 1047         NTFS_SB(vol) = sb;
 1048         if (vol->cluster_size > PAGE_SIZE) {
 1049                 ntfs_error("Partition cluster size is not supported yet (it "
 1050                            "is > max kernel blocksize).\n");
 1051                 goto ntfs_read_super_unl;
 1052         }
 1053         ntfs_debug(DEBUG_OTHER, "Done to init volume\n");
 1054         /* Inform the kernel that a device block is a NTFS cluster. */
 1055         sb->s_blocksize = vol->cluster_size;
 1056         sb->s_blocksize_bits = vol->cluster_size_bits;
 1057         if (blocksize != vol->cluster_size &&
 1058                         set_blocksize(sb->s_dev, sb->s_blocksize) < 0) {
 1059                 ntfs_error("Cluster size too small for device.\n");
 1060                 goto ntfs_read_super_unl;
 1061         }
 1062         ntfs_debug(DEBUG_OTHER, "set_blocksize\n");
 1063         /* Allocate an MFT record (MFT record can be smaller than a cluster). */
 1064         i = vol->cluster_size;
 1065         if (i < vol->mft_record_size)
 1066                 i = vol->mft_record_size;
 1067         if (!(vol->mft = ntfs_malloc(i)))
 1068                 goto ntfs_read_super_unl;
 1069 
 1070         /* Read at least the MFT record for $Mft. */
 1071         to_read = vol->mft_clusters_per_record;
 1072         if (to_read < 1)
 1073                 to_read = 1;
 1074         for (i = 0; i < to_read; i++) {
 1075                 if (!(bh = sb_bread(sb, vol->mft_lcn + i))) {
 1076                         ntfs_error("Could not read $Mft record 0\n");
 1077                         goto ntfs_read_super_mft;
 1078                 }
 1079                 ntfs_memcpy(vol->mft + ((__s64)i << vol->cluster_size_bits),
 1080                                                 bh->b_data, vol->cluster_size);
 1081                 brelse(bh);
 1082                 ntfs_debug(DEBUG_OTHER, "Read cluster 0x%x\n",
 1083                                                          vol->mft_lcn + i);
 1084         }
 1085         /* Check and fixup this MFT record */
 1086         if (!ntfs_check_mft_record(vol, vol->mft)){
 1087                 ntfs_error("Invalid $Mft record 0\n");
 1088                 goto ntfs_read_super_mft;
 1089         }
 1090         /* Inform the kernel about which super operations are available. */
 1091         sb->s_op = &ntfs_super_operations;
 1092         sb->s_magic = NTFS_SUPER_MAGIC;
 1093         sb->s_maxbytes = MAX_LFS_FILESIZE;
 1094         ntfs_debug(DEBUG_OTHER, "Reading special files\n");
 1095         if (ntfs_load_special_files(vol)) {
 1096                 ntfs_error("Error loading special files\n");
 1097                 goto ntfs_read_super_mft;
 1098         }
 1099         ntfs_debug(DEBUG_OTHER, "Getting RootDir\n");
 1100         /* Get the root directory. */
 1101         if (!(sb->s_root = d_alloc_root(iget(sb, FILE_root)))) {
 1102                 ntfs_error("Could not get root dir inode\n");
 1103                 goto ntfs_read_super_mft;
 1104         }
 1105 ntfs_read_super_ret:
 1106         ntfs_debug(DEBUG_OTHER, "read_super: done\n");
 1107         return sb;
 1108 ntfs_read_super_mft:
 1109         ntfs_free(vol->mft);
 1110 ntfs_read_super_unl:
 1111 ntfs_read_super_vol:
 1112         sb = NULL;
 1113         goto ntfs_read_super_ret;
 1114 }
 1115 
 1116 /* Define the filesystem */
 1117 static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);
 1118 
 1119 static int __init init_ntfs_fs(void)
 1120 {
 1121         /* Comment this if you trust klogd. There are reasons not to trust it */
 1122 #if defined(DEBUG) && !defined(MODULE)
 1123         console_verbose();
 1124 #endif
 1125         printk(KERN_NOTICE "NTFS driver v" NTFS_VERSION " [Flags: R/"
 1126 #ifdef CONFIG_NTFS_RW
 1127                         "W"
 1128 #else
 1129                         "O"
 1130 #endif
 1131 #ifdef DEBUG
 1132                         " DEBUG"
 1133 #endif
 1134 #ifdef MODULE
 1135                         " MODULE"
 1136 #endif
 1137                         "]\n");
 1138         SYSCTL(1);
 1139         ntfs_debug(DEBUG_OTHER, "registering %s\n", ntfs_fs_type.name);
 1140         /* Add this filesystem to the kernel table of filesystems. */
 1141         return register_filesystem(&ntfs_fs_type);
 1142 }
 1143 
 1144 static void __exit exit_ntfs_fs(void)
 1145 {
 1146         SYSCTL(0);
 1147         ntfs_debug(DEBUG_OTHER, "unregistering %s\n", ntfs_fs_type.name);
 1148         unregister_filesystem(&ntfs_fs_type);
 1149 }
 1150 
 1151 EXPORT_NO_SYMBOLS;
 1152 /*
 1153  * Not strictly true. The driver was written originally by Martin von Lwis.
 1154  * I am just maintaining and rewriting it.
 1155  */
 1156 MODULE_AUTHOR("Anton Altaparmakov <aia21@cus.cam.ac.uk>");
 1157 MODULE_DESCRIPTION("Linux NTFS driver");
 1158 MODULE_LICENSE("GPL");
 1159 #ifdef DEBUG
 1160 MODULE_PARM(ntdebug, "i");
 1161 MODULE_PARM_DESC(ntdebug, "Debug level");
 1162 #endif
 1163 
 1164 module_init(init_ntfs_fs)
 1165 module_exit(exit_ntfs_fs)
 1166 

Cache object: 68c57a881aedc316bb9a0a6696b18c8b


[ 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.