!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/fs/ntfs/   drwxr-xr-x
Free 318.39 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     fs.c (31.91 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/*
 * fs.c - NTFS driver for Linux 2.4.x
 *
 * Legato Systems, Inc. (http://www.legato.com) have sponsored Anton
 * Altaparmakov to develop NTFS on Linux since June 2001.
 *
 * Copyright (C) 1995-1997, 1999 Martin von Löwis
 * Copyright (C) 1996 Richard Russon
 * Copyright (C) 1996-1997 Régis Duchesne
 * Copyright (C) 2000-2001, Anton Altaparmakov (AIA)
 */

#include <linux/config.h>
#include <linux/errno.h>
#include "ntfstypes.h"
#include "struct.h"
#include "util.h"
#include "inode.h"
#include "super.h"
#include "dir.h"
#include "support.h"
#include "macros.h"
#include "sysctl.h"
#include "attr.h"
#include <linux/module.h>
#include <asm/uaccess.h>
#include <linux/locks.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/blkdev.h>
#include <asm/page.h>
#include <linux/nls.h>
#include <linux/ntfs_fs.h>

/* Forward declarations. */
static struct inode_operations ntfs_dir_inode_operations;
static struct file_operations ntfs_dir_operations;

#define ITEM_SIZE 2040

/* Io functions to user space. */
static void ntfs_putuser(ntfs_io* dest, void *src, ntfs_size_t len)
{
    copy_to_user(dest->param, src, len);
    dest->param += len;
}

#ifdef CONFIG_NTFS_RW
struct ntfs_getuser_update_vm_s {
    const char *user;
    struct inode *ino;
    loff_t off;
};

static void ntfs_getuser_update_vm(void *dest, ntfs_io *src, ntfs_size_t len)
{
    struct ntfs_getuser_update_vm_s *p = src->param;
    
    copy_from_user(dest, p->user, len);
    p->user += len;
    p->off += len;
}
#endif

/* loff_t is 64 bit signed, so is cool. */
static ssize_t ntfs_read(struct file *filp, char *buf, size_t count,loff_t *off)
{
    int error;
    ntfs_io io;
    ntfs_attribute *attr;
    ntfs_inode *ino = NTFS_LINO2NINO(filp->f_dentry->d_inode);

    /* Inode is not properly initialized. */
    if (!ino)
        return -EINVAL;
    ntfs_debug(DEBUG_OTHER, "ntfs_read %x, %Lx, %x ->",
           (unsigned)ino->i_number, (unsigned long long)*off,
           (unsigned)count);
    attr = ntfs_find_attr(ino, ino->vol->at_data, NULL);
    /* Inode has no unnamed data attribute. */
    if (!attr) {
        ntfs_debug(DEBUG_OTHER, "ntfs_read: $DATA not found!\n");
        return -EINVAL;
    }
    if (attr->flags & ATTR_IS_ENCRYPTED)
        return -EACCES;
    /* Read the data. */
    io.fn_put = ntfs_putuser;
    io.fn_get = 0;
    io.param = buf;
    io.size = count;
    error = ntfs_read_attr(ino, ino->vol->at_data, NULL, *off, &io);
    if (error && !io.size) {
        ntfs_debug(DEBUG_OTHER, "ntfs_read: read_attr failed with "
                "error %i, io size %u.\n", error, io.size);
        return error;
    }
    *off += io.size;
    ntfs_debug(DEBUG_OTHER, "ntfs_read: finished. read %u bytes.\n",
                                io.size);
    return io.size;
}

#ifdef CONFIG_NTFS_RW
static ssize_t ntfs_write(struct file *filp, const char *buf, size_t count,
        loff_t *pos)
{
    int err;
    struct inode *vfs_ino = filp->f_dentry->d_inode;
    ntfs_inode *ntfs_ino = NTFS_LINO2NINO(vfs_ino);
    ntfs_attribute *data;
    ntfs_io io;
    struct ntfs_getuser_update_vm_s param;

    if (!ntfs_ino)
        return -EINVAL;
    ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Entering for inode 0x%lx, "
            "*pos 0x%Lx, count 0x%x.\n", ntfs_ino->i_number, *pos,
            count);
    /* Allows to lock fs ro at any time. */
    if (vfs_ino->i_sb->s_flags & MS_RDONLY)
        return -EROFS;
    data = ntfs_find_attr(ntfs_ino, ntfs_ino->vol->at_data, NULL);
    if (!data)
        return -EINVAL;
    /* Evaluating O_APPEND is the file system's job... */
    if (filp->f_flags & O_APPEND)
        *pos = vfs_ino->i_size;
    if (!data->resident && *pos + count > data->allocated) {
        err = ntfs_extend_attr(ntfs_ino, data, *pos + count);
        if (err < 0)
            return err;
    }
    param.user = buf;
    param.ino = vfs_ino;
    param.off = *pos;
    io.fn_put = 0;
    io.fn_get = ntfs_getuser_update_vm;
    io.param = &param;
    io.size = count;
    io.do_read = 0;
    err = ntfs_readwrite_attr(ntfs_ino, data, *pos, &io);
    ntfs_debug(DEBUG_LINUX, __FUNCTION__ "(): Returning %i\n", -err);
    if (!err) {
        *pos += io.size;
        if (*pos > vfs_ino->i_size)
            vfs_ino->i_size = *pos;
        mark_inode_dirty(vfs_ino);
        return io.size;
    }
    return err;
}
#endif

struct ntfs_filldir {
    struct inode *dir;
    filldir_t filldir;
    unsigned int type;
    u32 ph, pl;
    void *dirent;
    char *name;
    int namelen;
    int ret_code;
};

static int ntfs_printcb(ntfs_u8 *entry, void *param)
{
    unsigned long inum = NTFS_GETU64(entry) & 0xffffffffffff;
    struct ntfs_filldir *nf = param;
    u32 flags = NTFS_GETU32(entry + 0x48);
    char show_sys_files = 0;
    u8 name_len = NTFS_GETU8(entry + 0x50);
    u8 name_type = NTFS_GETU8(entry + 0x51);
    int err;
    unsigned file_type;

    switch (nf->type) {
    case ngt_dos:
        /* Don't display long names. */
        if (!(name_type & 2))
            return 0;
        break;
    case ngt_nt:
        /* Don't display short-only names. */
        if ((name_type & 3) == 2)
            return 0;
        break;
    case ngt_posix:
        break;
    case ngt_full:
        show_sys_files = 1;
        break;
    default:
        BUG();
    }
    err = ntfs_encodeuni(NTFS_INO2VOL(nf->dir), (ntfs_u16*)(entry + 0x52),
            name_len, &nf->name, &nf->namelen);
    if (err) {
        ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping "
                "unrepresentable file.\n");
        err = 0;
        goto err_ret;
    }
    if (!show_sys_files && inum < 0x10UL) {
        ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping system "
                "file (%s).\n", nf->name);
        err = 0;
        goto err_ret;
    }
    /* Do not return ".", as this is faked. */
    if (nf->namelen == 1 && nf->name[0] == '.') {
        ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Skipping \".\"\n");
        err = 0;
        goto err_ret;
    }
    nf->name[nf->namelen] = 0;
    if (flags & 0x10000000) /* FILE_ATTR_DUP_FILE_NAME_INDEX_PRESENT */
        file_type = DT_DIR;
    else
        file_type = DT_REG;
    ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling filldir for %s with "
            "len %i, f_pos 0x%Lx, inode %lu, %s.\n",
            nf->name, nf->namelen, (loff_t)(nf->ph << 16) | nf->pl,
            inum, file_type == DT_DIR ? "DT_DIR" : "DT_REG");
    /*
     * Userspace side of filldir expects an off_t rather than an loff_t.
     * And it also doesn't like the most significant bit being set as it
     * then considers the value to be negative. Thus this implementation
     * limits the number of index records to 32766, which should be plenty.
     */
    err = nf->filldir(nf->dirent, nf->name, nf->namelen,
            (loff_t)(nf->ph << 16) | nf->pl, inum, file_type);
    if (err)
        nf->ret_code = err;
err_ret:
    nf->namelen = 0;
    ntfs_free(nf->name);
    nf->name = NULL;
    return err;
}

/*
 * readdir returns '.', then '..', then the directory entries in sequence.
 * As the root directory contains an entry for itself, '.' is not emulated for
 * the root directory.
 */
static int ntfs_readdir(struct file* filp, void *dirent, filldir_t filldir)
{
    struct inode *dir = filp->f_dentry->d_inode;
    int err;
    struct ntfs_filldir cb;

    cb.ret_code = 0;
    cb.pl = filp->f_pos & 0xffff;
    cb.ph = (filp->f_pos >> 16) & 0x7fff;
    filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
    ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Entering for inode %lu, "
            "f_pos 0x%Lx, i_mode 0x%x, i_count %lu.\n", dir->i_ino,
            filp->f_pos, (unsigned int)dir->i_mode,
            atomic_read(&dir->i_count));
    if (!cb.ph) {
        /* Start of directory. Emulate "." and "..". */
        if (!cb.pl) {
            ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling "
                    "filldir for . with len 1, f_pos 0x%Lx, "
                    "inode %lu, DT_DIR.\n", filp->f_pos,
                    dir->i_ino);
            cb.ret_code = filldir(dirent, ".", 1, filp->f_pos,
                    dir->i_ino, DT_DIR);
            if (cb.ret_code)
                goto done;
            cb.pl++;
            filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
        }
        if (cb.pl == (u32)1) {
            ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Calling "
                    "filldir for .. with len 2, f_pos 0x%Lx, "
                    "inode %lu, DT_DIR.\n", filp->f_pos,
                    filp->f_dentry->d_parent->d_inode->i_ino);
            cb.ret_code = filldir(dirent, "..", 2, filp->f_pos,
                    filp->f_dentry->d_parent->d_inode->i_ino,
                    DT_DIR);
            if (cb.ret_code)
                goto done;
            cb.pl++;
            filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
        }
    } else if (cb.ph >= 0x7fff)
        /* End of directory. */
        goto done;
    cb.dir = dir;
    cb.filldir = filldir;
    cb.dirent = dirent;
    cb.type = NTFS_INO2VOL(dir)->ngt;
    do {
        ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Looking for next "
                "file using ntfs_getdir_unsorted(), f_pos "
                "0x%Lx.\n", (loff_t)(cb.ph << 16) | cb.pl);
        err = ntfs_getdir_unsorted(NTFS_LINO2NINO(dir), &cb.ph, &cb.pl,
                ntfs_printcb, &cb);
    } while (!err && !cb.ret_code && cb.ph < 0x7fff);
    filp->f_pos = (loff_t)(cb.ph << 16) | cb.pl;
    ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): After ntfs_getdir_unsorted()"
            " calls, f_pos 0x%Lx.\n", filp->f_pos);
    if (!err) {
done:
#ifdef DEBUG
        if (!cb.ret_code)
            ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): EOD, f_pos "
                    "0x%Lx, returning 0.\n", filp->f_pos);
        else 
            ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): filldir "
                    "returned %i, returning 0, f_pos "
                    "0x%Lx.\n", cb.ret_code, filp->f_pos);
#endif
        return 0;
    }
    ntfs_debug(DEBUG_OTHER, __FUNCTION__ "(): Returning %i, f_pos 0x%Lx.\n",
            err, filp->f_pos);
    return err;
}

/* Copied from vfat driver. */
static int simple_getbool(char *s, int *setval)
{
    if (s) {
        if (!strcmp(s, "1") || !strcmp(s, "yes") || !strcmp(s, "true"))
            *setval = 1;
        else if (!strcmp(s, "0") || !strcmp(s, "no") ||
                            !strcmp(s, "false"))
            *setval = 0;
        else
            return 0;
    } else
        *setval = 1;
    return 1;
}

/*
 * This needs to be outside parse_options() otherwise a remount will reset
 * these unintentionally.
 */
static void init_ntfs_super_block(ntfs_volume* vol)
{
    vol->uid = vol->gid = 0;
    vol->umask = 0077;
    vol->ngt = ngt_nt;
    vol->nls_map = (void*)-1;
    vol->mft_zone_multiplier = -1;
}

/* Parse the (re)mount options. */
static int parse_options(ntfs_volume *vol, char *opt)
{
    char *value;        /* Defaults if not specified and !remount. */
    ntfs_uid_t uid = -1;    /* 0, root user only */
    ntfs_gid_t gid = -1;    /* 0, root user only */
    int umask = -1;        /* 0077, owner access only */
    unsigned int ngt = -1;    /* ngt_nt */
    void *nls_map = NULL;    /* Try to load the default NLS. */
    int use_utf8 = -1;    /* If no NLS specified and loading the default
                   NLS failed use utf8. */
    int mft_zone_mul = -1;    /* 1 */

    if (!opt)
        goto done;
    for (opt = strtok(opt, ","); opt; opt = strtok(NULL, ",")) {
        if ((value = strchr(opt, '=')) != NULL)
            *value ++= '\0';
        if (strcmp(opt, "uid") == 0) {
            if (!value || !*value)
                goto needs_arg;
            uid = simple_strtoul(value, &value, 0);
            if (*value) {
                printk(KERN_ERR "NTFS: uid invalid argument\n");
                return 0;
            }
        } else if (strcmp(opt, "gid") == 0) {
            if (!value || !*value)
                goto needs_arg;
            gid = simple_strtoul(value, &value, 0);
            if (*value) {
                printk(KERN_ERR "NTFS: gid invalid argument\n");
                return 0;
            }
        } else if (strcmp(opt, "umask") == 0) {
            if (!value || !*value)
                goto needs_arg;
            umask = simple_strtoul(value, &value, 0);
            if (*value) {
                printk(KERN_ERR "NTFS: umask invalid "
                        "argument\n");
                return 0;
            }
        } else if (strcmp(opt, "mft_zone_multiplier") == 0) {
            unsigned long ul;

            if (!value || !*value)
                goto needs_arg;
            ul = simple_strtoul(value, &value, 0);
            if (*value) {
                printk(KERN_ERR "NTFS: mft_zone_multiplier "
                        "invalid argument\n");
                return 0;
            }
            if (ul >= 1 && ul <= 4)
                mft_zone_mul = ul;
            else {
                mft_zone_mul = 1;
                printk(KERN_WARNING "NTFS: mft_zone_multiplier "
                          "out of range. Setting to 1.\n");
            }
        } else if (strcmp(opt, "posix") == 0) {
            int val;
            if (!value || !*value)
                goto needs_arg;
            if (!simple_getbool(value, &val))
                goto needs_bool;
            ngt = val ? ngt_posix : ngt_nt;
        } else if (strcmp(opt, "show_sys_files") == 0) {
            int val = 0;
            if (!value || !*value)
                val = 1;
            else if (!simple_getbool(value, &val))
                goto needs_bool;
            ngt = val ? ngt_full : ngt_nt;
        } else if (strcmp(opt, "iocharset") == 0) {
            if (!value || !*value)
                goto needs_arg;
            nls_map = load_nls(value);
            if (!nls_map) {
                printk(KERN_ERR "NTFS: charset not found");
                return 0;
            }
        } else if (strcmp(opt, "utf8") == 0) {
            int val = 0;
            if (!value || !*value)
                val = 1;
            else if (!simple_getbool(value, &val))
                goto needs_bool;
            use_utf8 = val;
        } else {
            printk(KERN_ERR "NTFS: unkown option '%s'\n", opt);
            return 0;
        }
    }
done:
    if (use_utf8 == -1) {
        /* utf8 was not specified at all. */
        if (!nls_map) {
            /*
             * No NLS was specified. If first mount, load the
             * default NLS, otherwise don't change the NLS setting.
             */
            if (vol->nls_map == (void*)-1)
                vol->nls_map = load_nls_default();
        } else {
            /* If an NLS was already loaded, unload it first. */
            if (vol->nls_map && vol->nls_map != (void*)-1)
                unload_nls(vol->nls_map);
            /* Use the specified NLS. */
            vol->nls_map = nls_map;
        }
    } else {
        /* utf8 was specified. */
        if (use_utf8 && nls_map) {
            unload_nls(nls_map);
            printk(KERN_ERR "NTFS: utf8 cannot be combined with "
                    "iocharset.\n");
            return 0;
        }
        /* If an NLS was already loaded, unload it first. */
        if (vol->nls_map && vol->nls_map != (void*)-1)
            unload_nls(vol->nls_map);
        if (!use_utf8) {
            /* utf8 was specified as false. */
            if (!nls_map)
                /* No NLS was specified, load the default. */
                vol->nls_map = load_nls_default();
            else
                /* Use the specified NLS. */
                vol->nls_map = nls_map;
        } else
            /* utf8 was specified as true. */
            vol->nls_map = NULL;
    }
    if (uid != -1)
        vol->uid = uid;
    if (gid != -1)
        vol->gid = gid;
    if (umask != -1)
        vol->umask = (ntmode_t)umask;
    if (ngt != -1)
        vol->ngt = ngt;
    if (mft_zone_mul != -1) {
        /* mft_zone_multiplier was specified. */
        if (vol->mft_zone_multiplier != -1) {
            /* This is a remount, ignore a change and warn user. */
            if (vol->mft_zone_multiplier != mft_zone_mul)
                printk(KERN_WARNING "NTFS: Ignoring changes in "
                        "mft_zone_multiplier on "
                        "remount. If you want to "
                        "change this you need to "
                        "umount and mount again.\n");
        } else
            /* Use the specified multiplier. */
            vol->mft_zone_multiplier = mft_zone_mul;
    } else if (vol->mft_zone_multiplier == -1)
        /* No multiplier specified and first mount, so set default. */
        vol->mft_zone_multiplier = 1;
    return 1;
needs_arg:
    printk(KERN_ERR "NTFS: %s needs an argument", opt);
    return 0;
needs_bool:
    printk(KERN_ERR "NTFS: %s needs boolean argument", opt);
    return 0;
}
            
static struct dentry *ntfs_lookup(struct inode *dir, struct dentry *d)
{
    struct inode *res = 0;
    char *item = 0;
    ntfs_iterate_s walk;
    int err;
    
    ntfs_debug(DEBUG_NAME1, __FUNCTION__ "(): Looking up %s in directory "
            "ino 0x%x.\n", d->d_name.name, (unsigned)dir->i_ino);
    walk.name = NULL;
    walk.namelen = 0;
    /* Convert to wide string. */
    err = ntfs_decodeuni(NTFS_INO2VOL(dir), (char*)d->d_name.name,
                   d->d_name.len, &walk.name, &walk.namelen);
    if (err)
        goto err_ret;
    item = ntfs_malloc(ITEM_SIZE);
    if (!item) {
        err = -ENOMEM;
        goto err_ret;
    }
    /* ntfs_getdir will place the directory entry into item, and the first
     * long long is the MFT record number. */
    walk.type = BY_NAME;
    walk.dir = NTFS_LINO2NINO(dir);
    walk.result = item;
    if (ntfs_getdir_byname(&walk))
        res = iget(dir->i_sb, NTFS_GETU32(item));
    d_add(d, res);
    ntfs_free(item);
    ntfs_free(walk.name);
    /* Always return success, the dcache will handle negative entries. */
    return NULL;
err_ret:
    ntfs_free(walk.name);
    return ERR_PTR(err);
}

static struct file_operations ntfs_file_operations = {
    llseek:        generic_file_llseek,
    read:        ntfs_read,
#ifdef CONFIG_NTFS_RW
    write:        ntfs_write,
#endif
    open:        generic_file_open,
};

static struct inode_operations ntfs_inode_operations;

#ifdef CONFIG_NTFS_RW
static int ntfs_create(struct inode* dir, struct dentry *d, int mode)
{
    struct inode *r = 0;
    ntfs_inode *ino = 0;
    ntfs_volume *vol;
    int error = 0;
    ntfs_attribute *si;

    r = new_inode(dir->i_sb);
    if (!r) {
        error = -ENOMEM;
        goto fail;
    }
    ntfs_debug(DEBUG_OTHER, "ntfs_create %s\n", d->d_name.name);
    vol = NTFS_INO2VOL(dir);
    ino = NTFS_LINO2NINO(r);
    error = ntfs_alloc_file(NTFS_LINO2NINO(dir), ino, (char*)d->d_name.name,
                d->d_name.len);
    if (error) {
        ntfs_error("ntfs_alloc_file FAILED: error = %i", error);
        goto fail;
    }
    /* Not doing this one was causing a huge amount of corruption! Now the
     * bugger bytes the dust! (-8 (AIA) */
    r->i_ino = ino->i_number;
    error = ntfs_update_inode(ino);
    if (error)
        goto fail;
    error = ntfs_update_inode(NTFS_LINO2NINO(dir));
    if (error)
        goto fail;
    r->i_uid = vol->uid;
    r->i_gid = vol->gid;
    /* FIXME: dirty? dev? */
    /* Get the file modification times from the standard information. */
    si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
    if (si) {
        char *attr = si->d.data;
        r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
        r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
        r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
    }
    /* It's not a directory */
    r->i_op = &ntfs_inode_operations;
    r->i_fop = &ntfs_file_operations;
    r->i_mode = S_IFREG | S_IRUGO;
#ifdef CONFIG_NTFS_RW
    r->i_mode |= S_IWUGO;
#endif
    r->i_mode &= ~vol->umask;
    insert_inode_hash(r);
    d_instantiate(d, r);
    return 0;
 fail:
    if (r)
        iput(r);
    return error;
}

static int _linux_ntfs_mkdir(struct inode *dir, struct dentry* d, int mode)
{
    int error;
    struct inode *r = 0;
    ntfs_volume *vol;
    ntfs_inode *ino;
    ntfs_attribute *si;

    ntfs_debug (DEBUG_DIR1, "mkdir %s in %x\n", d->d_name.name, dir->i_ino);
    error = -ENAMETOOLONG;
    if (d->d_name.len > /* FIXME: */ 255)
        goto out;
    error = -EIO;
    r = new_inode(dir->i_sb);
    if (!r)
        goto out;
    vol = NTFS_INO2VOL(dir);
    ino = NTFS_LINO2NINO(r);
    error = ntfs_mkdir(NTFS_LINO2NINO(dir), d->d_name.name, d->d_name.len,
               ino);
    if (error)
        goto out;
    /* Not doing this one was causing a huge amount of corruption! Now the
     * bugger bytes the dust! (-8 (AIA) */
    r->i_ino = ino->i_number;
    r->i_uid = vol->uid;
    r->i_gid = vol->gid;
    si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
    if (si) {
        char *attr = si->d.data;
        r->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
        r->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
        r->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
    }
    /* It's a directory. */
    r->i_op = &ntfs_dir_inode_operations;
    r->i_fop = &ntfs_dir_operations;
    r->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
#ifdef CONFIG_NTFS_RW
    r->i_mode |= S_IWUGO;
#endif
    r->i_mode &= ~vol->umask;    
    
    insert_inode_hash(r);
    d_instantiate(d, r);
    error = 0;
 out:
     ntfs_debug (DEBUG_DIR1, "mkdir returns %d\n", error);
    return error;
}
#endif

static struct file_operations ntfs_dir_operations = {
    read:        generic_read_dir,
    readdir:    ntfs_readdir,
};

static struct inode_operations ntfs_dir_inode_operations = {
    lookup:        ntfs_lookup,
#ifdef CONFIG_NTFS_RW
    create:        ntfs_create,
    mkdir:        _linux_ntfs_mkdir,
#endif
};

/* ntfs_read_inode() is called by the Virtual File System (the kernel layer 
 * that deals with filesystems) when iget is called requesting an inode not
 * already present in the inode table. Typically filesystems have separate
 * inode_operations for directories, files and symlinks. */
static void ntfs_read_inode(struct inode* inode)
{
    ntfs_volume *vol;
    ntfs_inode *ino;
    ntfs_attribute *data;
    ntfs_attribute *si;

    vol = NTFS_INO2VOL(inode);
    inode->i_mode = 0;
    ntfs_debug(DEBUG_OTHER, "ntfs_read_inode 0x%lx\n", inode->i_ino);
    switch (inode->i_ino) {
        /* Those are loaded special files. */
    case FILE_Mft:
        if (!vol->mft_ino || ((vol->ino_flags & 1) == 0))
            goto sys_file_error;
        ntfs_memcpy(&inode->u.ntfs_i, vol->mft_ino, sizeof(ntfs_inode));
        ino = vol->mft_ino;
        vol->mft_ino = &inode->u.ntfs_i;
        vol->ino_flags &= ~1;
        ntfs_free(ino);
        ino = vol->mft_ino;
        ntfs_debug(DEBUG_OTHER, "Opening $MFT!\n");
        break;
    case FILE_MftMirr:
        if (!vol->mftmirr || ((vol->ino_flags & 2) == 0))
            goto sys_file_error;
        ntfs_memcpy(&inode->u.ntfs_i, vol->mftmirr, sizeof(ntfs_inode));
        ino = vol->mftmirr;
        vol->mftmirr = &inode->u.ntfs_i;
        vol->ino_flags &= ~2;
        ntfs_free(ino);
        ino = vol->mftmirr;
        ntfs_debug(DEBUG_OTHER, "Opening $MFTMirr!\n");
        break;
    case FILE_BitMap:
        if (!vol->bitmap || ((vol->ino_flags & 4) == 0))
            goto sys_file_error;
        ntfs_memcpy(&inode->u.ntfs_i, vol->bitmap, sizeof(ntfs_inode));
        ino = vol->bitmap;
        vol->bitmap = &inode->u.ntfs_i;
        vol->ino_flags &= ~4;
        ntfs_free(ino);
        ino = vol->bitmap;
        ntfs_debug(DEBUG_OTHER, "Opening $Bitmap!\n");
        break;
    case FILE_LogFile ... FILE_AttrDef:
    /* No need to log root directory accesses. */
    case FILE_Boot ... FILE_UpCase:
        ntfs_debug(DEBUG_OTHER, "Opening system file %i!\n",
                inode->i_ino);
    default:
        ino = &inode->u.ntfs_i;
        if (!ino || ntfs_init_inode(ino, NTFS_INO2VOL(inode),
                                inode->i_ino))
        {
            ntfs_debug(DEBUG_OTHER, "NTFS: Error loading inode "
                    "0x%x\n", (unsigned int)inode->i_ino);
            return;
        }
    }
    /* Set uid/gid from mount options */
    inode->i_uid = vol->uid;
    inode->i_gid = vol->gid;
    inode->i_nlink = 1;
    /* Use the size of the data attribute as file size */
    data = ntfs_find_attr(ino, vol->at_data, NULL);
    if (!data)
        inode->i_size = 0;
    else
        inode->i_size = data->size;
    /* Get the file modification times from the standard information. */
    si = ntfs_find_attr(ino, vol->at_standard_information, NULL);
    if (si) {
        char *attr = si->d.data;
        inode->i_atime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 0x18));
        inode->i_ctime = ntfs_ntutc2unixutc(NTFS_GETU64(attr));
        inode->i_mtime = ntfs_ntutc2unixutc(NTFS_GETU64(attr + 8));
    }
    /* If it has an index root, it's a directory. */
    if (ntfs_find_attr(ino, vol->at_index_root, "$I30")) {
        ntfs_attribute *at;
        at = ntfs_find_attr(ino, vol->at_index_allocation, "$I30");
        inode->i_size = at ? at->size : 0;
        inode->i_op = &ntfs_dir_inode_operations;
        inode->i_fop = &ntfs_dir_operations;
        inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
    } else {
        inode->i_op = &ntfs_inode_operations;
        inode->i_fop = &ntfs_file_operations;
        inode->i_mode = S_IFREG | S_IRUGO;
    }
#ifdef CONFIG_NTFS_RW
    if (!data || !(data->flags & (ATTR_IS_COMPRESSED | ATTR_IS_ENCRYPTED)))
        inode->i_mode |= S_IWUGO;
#endif
    inode->i_mode &= ~vol->umask;
    return;
sys_file_error:
    ntfs_error("Critical error. Tried to call ntfs_read_inode() before we "
        "have completed read_super() or VFS error.\n");
    // FIXME: Should we panic() at this stage?
}

#ifdef CONFIG_NTFS_RW
static void ntfs_write_inode(struct inode *ino, int unused)
{
    lock_kernel();
    ntfs_debug(DEBUG_LINUX, "ntfs_write_inode 0x%x\n", ino->i_ino);
    ntfs_update_inode(NTFS_LINO2NINO(ino));
    unlock_kernel();
}
#endif

static void _ntfs_clear_inode(struct inode *inode)
{
    ntfs_inode *ino;
    ntfs_volume *vol;
    
    lock_kernel();
    ntfs_debug(DEBUG_OTHER, "_ntfs_clear_inode 0x%x\n", inode->i_ino);
    vol = NTFS_INO2VOL(inode);
    if (!vol)
        ntfs_error("_ntfs_clear_inode: vol = NTFS_INO2VOL(inode) is "
                "NULL.\n");
    switch (inode->i_ino) {
    case FILE_Mft:
        if (vol->mft_ino && ((vol->ino_flags & 1) == 0)) {
            ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
            ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
            vol->mft_ino = ino;
            vol->ino_flags |= 1;
            goto unl_out;
        }
        break;
    case FILE_MftMirr:
        if (vol->mftmirr && ((vol->ino_flags & 2) == 0)) {
            ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
            ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
            vol->mftmirr = ino;
            vol->ino_flags |= 2;
            goto unl_out;
        }
        break;
    case FILE_BitMap:
        if (vol->bitmap && ((vol->ino_flags & 4) == 0)) {
            ino = (ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
            ntfs_memcpy(ino, &inode->u.ntfs_i, sizeof(ntfs_inode));
            vol->bitmap = ino;
            vol->ino_flags |= 4;
            goto unl_out;
        }
        break;
    default:
        /* Nothing. Just clear the inode and exit. */
    }
    ntfs_clear_inode(&inode->u.ntfs_i);
unl_out:
    unlock_kernel();
    return;
}

/* Called when umounting a filesystem by do_umount() in fs/super.c. */
static void ntfs_put_super(struct super_block *sb)
{
    ntfs_volume *vol;

    ntfs_debug(DEBUG_OTHER, "ntfs_put_super\n");
    vol = NTFS_SB2VOL(sb);
    ntfs_release_volume(vol);
    if (vol->nls_map)
        unload_nls(vol->nls_map);
    ntfs_debug(DEBUG_OTHER, "ntfs_put_super: done\n");
}

/* Called by the kernel when asking for stats. */
static int ntfs_statfs(struct super_block *sb, struct statfs *sf)
{
    struct inode *mft;
    ntfs_volume *vol;
    __s64 size;
    int error;

    ntfs_debug(DEBUG_OTHER, "ntfs_statfs\n");
    vol = NTFS_SB2VOL(sb);
    sf->f_type = NTFS_SUPER_MAGIC;
    sf->f_bsize = vol->cluster_size;
    error = ntfs_get_volumesize(NTFS_SB2VOL(sb), &size);
    if (error)
        return error;
    sf->f_blocks = size;    /* Volumesize is in clusters. */
    size = (__s64)ntfs_get_free_cluster_count(vol->bitmap);
    /* Just say zero if the call failed. */
    if (size < 0LL)
        size = 0;
    sf->f_bfree = sf->f_bavail = size;
    ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling mft = iget(sb, "
            "FILE_Mft)\n");
    mft = iget(sb, FILE_Mft);
    ntfs_debug(DEBUG_OTHER, "ntfs_statfs: iget(sb, FILE_Mft) returned "
            "0x%x\n", mft);
    if (!mft)
        return -EIO;
    sf->f_files = mft->i_size >> vol->mft_record_size_bits;
    ntfs_debug(DEBUG_OTHER, "ntfs_statfs: calling iput(mft)\n");
    iput(mft);
    /* Should be read from volume. */
    sf->f_namelen = 255;
    return 0;
}

/* Called when remounting a filesystem by do_remount_sb() in fs/super.c. */
static int ntfs_remount_fs(struct super_block *sb, int *flags, char *options)
{
    if (!parse_options(NTFS_SB2VOL(sb), options))
        return -EINVAL;
    return 0;
}

/* Define the super block operation that are implemented */
static struct super_operations ntfs_super_operations = {
    read_inode:    ntfs_read_inode,
#ifdef CONFIG_NTFS_RW
    write_inode:    ntfs_write_inode,
#endif
    put_super:    ntfs_put_super,
    statfs:        ntfs_statfs,
    remount_fs:    ntfs_remount_fs,
    clear_inode:    _ntfs_clear_inode,
};

/**
 * is_boot_sector_ntfs - check an NTFS boot sector for validity
 * @b:        buffer containing bootsector to check
 * 
 * Check whether @b contains a valid NTFS boot sector.
 * Return 1 if @b is a valid NTFS bootsector or 0 if not.
 */
static int is_boot_sector_ntfs(ntfs_u8 *b)
{
    ntfs_u32 i;

    /* FIXME: We don't use checksumming yet as NT4(SP6a) doesn't either...
     * But we might as well have the code ready to do it. (AIA) */
#if 0
    /* Calculate the checksum. */
    if (b < b + 0x50) {
        ntfs_u32 *u;
        ntfs_u32 *bi = (ntfs_u32 *)(b + 0x50);
        
        for (u = bi, i = 0; u < bi; ++u)
            i += NTFS_GETU32(*u);
    }
#endif
    /* Check magic is "NTFS    " */
    if (b[3] != 0x4e) goto not_ntfs;
    if (b[4] != 0x54) goto not_ntfs;
    if (b[5] != 0x46) goto not_ntfs;
    if (b[6] != 0x53) goto not_ntfs;
    for (i = 7; i < 0xb; ++i)
        if (b[i] != 0x20) goto not_ntfs;
    /* Check bytes per sector value is between 512 and 4096. */
    if (b[0xb] != 0) goto not_ntfs;
    if (b[0xc] > 0x10) goto not_ntfs;
    /* Check sectors per cluster value is valid. */
    switch (b[0xd]) {
    case 1: case 2: case 4: case 8: case 16:
    case 32: case 64: case 128:
        break;
    default:
        goto not_ntfs;
    }
    /* Check reserved sectors value and four other fields are zero. */
    for (i = 0xe; i < 0x15; ++i) 
        if (b[i] != 0) goto not_ntfs;
    if (b[0x16] != 0) goto not_ntfs;
    if (b[0x17] != 0) goto not_ntfs;
    for (i = 0x20; i < 0x24; ++i)
        if (b[i] != 0) goto not_ntfs;
    /* Check clusters per file record segment value is valid. */
    if (b[0x40] < 0xe1 || b[0x40] > 0xf7) {
        switch (b[0x40]) {
        case 1: case 2: case 4: case 8: case 16: case 32: case 64:
            break;
        default:
            goto not_ntfs;
        }
    }
    /* Check clusters per index block value is valid. */
    if (b[0x44] < 0xe1 || b[0x44] > 0xf7) {
        switch (b[0x44]) {
        case 1: case 2: case 4: case 8: case 16: case 32: case 64:
            break;
        default:
            goto not_ntfs;
        }
    }
    return 1;
not_ntfs:
    return 0;
}

/* Called to mount a filesystem by read_super() in fs/super.c.
 * Return a super block, the main structure of a filesystem.
 *
 * NOTE : Don't store a pointer to an option, as the page containing the
 * options is freed after ntfs_read_super() returns.
 *
 * NOTE : A context switch can happen in kernel code only if the code blocks
 * (= calls schedule() in kernel/sched.c). */
struct super_block *ntfs_read_super(struct super_block *sb, void *options,
        int silent)
{
    ntfs_volume *vol;
    struct buffer_head *bh;
    int i, to_read, blocksize;

    ntfs_debug(DEBUG_OTHER, "ntfs_read_super\n");
    vol = NTFS_SB2VOL(sb);
    init_ntfs_super_block(vol);
    if (!parse_options(vol, (char*)options))
        goto ntfs_read_super_vol;
    blocksize = get_hardsect_size(sb->s_dev);
    if (blocksize < 512)
        blocksize = 512;
    if (set_blocksize(sb->s_dev, blocksize) < 0) {
        ntfs_error("Unable to set blocksize %d.\n", blocksize);
        goto ntfs_read_super_vol;
    }
    sb->s_blocksize = blocksize;
    /* Read the super block (boot block). */
    if (!(bh = sb_bread(sb, 0))) {
        ntfs_error("Reading super block failed\n");
        goto ntfs_read_super_unl;
    }
    ntfs_debug(DEBUG_OTHER, "Done reading boot block\n");
    /* Check for valid 'NTFS' boot sector. */
    if (!is_boot_sector_ntfs(bh->b_data)) {
        ntfs_debug(DEBUG_OTHER, "Not a NTFS volume\n");
        bforget(bh);
        goto ntfs_read_super_unl;
    }
    ntfs_debug(DEBUG_OTHER, "Going to init volume\n");
    if (ntfs_init_volume(vol, bh->b_data) < 0) {
        ntfs_debug(DEBUG_OTHER, "Init volume failed.\n");
        bforget(bh);
        goto ntfs_read_super_unl;
    }
    ntfs_debug(DEBUG_OTHER, "$Mft at cluster 0x%lx\n", vol->mft_lcn);
    brelse(bh);
    NTFS_SB(vol) = sb;
    if (vol->cluster_size > PAGE_SIZE) {
        ntfs_error("Partition cluster size is not supported yet (it "
               "is > max kernel blocksize).\n");
        goto ntfs_read_super_unl;
    }
    ntfs_debug(DEBUG_OTHER, "Done to init volume\n");
    /* Inform the kernel that a device block is a NTFS cluster. */
    sb->s_blocksize = vol->cluster_size;
    sb->s_blocksize_bits = vol->cluster_size_bits;
    if (blocksize != vol->cluster_size &&
            set_blocksize(sb->s_dev, sb->s_blocksize) < 0) {
        ntfs_error("Cluster size too small for device.\n");
        goto ntfs_read_super_unl;
    }
    ntfs_debug(DEBUG_OTHER, "set_blocksize\n");
    /* Allocate an MFT record (MFT record can be smaller than a cluster). */
    i = vol->cluster_size;
    if (i < vol->mft_record_size)
        i = vol->mft_record_size;
    if (!(vol->mft = ntfs_malloc(i)))
        goto ntfs_read_super_unl;

    /* Read at least the MFT record for $Mft. */
    to_read = vol->mft_clusters_per_record;
    if (to_read < 1)
        to_read = 1;
    for (i = 0; i < to_read; i++) {
        if (!(bh = sb_bread(sb, vol->mft_lcn + i))) {
            ntfs_error("Could not read $Mft record 0\n");
            goto ntfs_read_super_mft;
        }
        ntfs_memcpy(vol->mft + ((__s64)i << vol->cluster_size_bits),
                        bh->b_data, vol->cluster_size);
        brelse(bh);
        ntfs_debug(DEBUG_OTHER, "Read cluster 0x%x\n",
                             vol->mft_lcn + i);
    }
    /* Check and fixup this MFT record */
    if (!ntfs_check_mft_record(vol, vol->mft)){
        ntfs_error("Invalid $Mft record 0\n");
        goto ntfs_read_super_mft;
    }
    /* Inform the kernel about which super operations are available. */
    sb->s_op = &ntfs_super_operations;
    sb->s_magic = NTFS_SUPER_MAGIC;
    sb->s_maxbytes = ~0ULL >> 1;
    ntfs_debug(DEBUG_OTHER, "Reading special files\n");
    if (ntfs_load_special_files(vol)) {
        ntfs_error("Error loading special files\n");
        goto ntfs_read_super_mft;
    }
    ntfs_debug(DEBUG_OTHER, "Getting RootDir\n");
    /* Get the root directory. */
    if (!(sb->s_root = d_alloc_root(iget(sb, FILE_root)))) {
        ntfs_error("Could not get root dir inode\n");
        goto ntfs_read_super_mft;
    }
ntfs_read_super_ret:
    ntfs_debug(DEBUG_OTHER, "read_super: done\n");
    return sb;
ntfs_read_super_mft:
    ntfs_free(vol->mft);
ntfs_read_super_unl:
ntfs_read_super_vol:
    sb = NULL;
    goto ntfs_read_super_ret;
}

/* Define the filesystem */
static DECLARE_FSTYPE_DEV(ntfs_fs_type, "ntfs", ntfs_read_super);

static int __init init_ntfs_fs(void)
{
    /* Comment this if you trust klogd. There are reasons not to trust it */
#if defined(DEBUG) && !defined(MODULE)
    console_verbose();
#endif
    printk(KERN_NOTICE "NTFS driver v" NTFS_VERSION " [Flags: R/"
#ifdef CONFIG_NTFS_RW
            "W"
#else
            "O"
#endif
#ifdef DEBUG
            " DEBUG"
#endif
#ifdef MODULE
            " MODULE"
#endif
            "]\n");
    SYSCTL(1);
    ntfs_debug(DEBUG_OTHER, "registering %s\n", ntfs_fs_type.name);
    /* Add this filesystem to the kernel table of filesystems. */
    return register_filesystem(&ntfs_fs_type);
}

static void __exit exit_ntfs_fs(void)
{
    SYSCTL(0);
    ntfs_debug(DEBUG_OTHER, "unregistering %s\n", ntfs_fs_type.name);
    unregister_filesystem(&ntfs_fs_type);
}

EXPORT_NO_SYMBOLS;
/*
 * Not strictly true. The driver was written originally by Martin von Löwis.
 * I am just maintaining and rewriting it.
 */
MODULE_AUTHOR("Anton Altaparmakov <aia21@cus.cam.ac.uk>");
MODULE_DESCRIPTION("Linux NTFS driver");
MODULE_LICENSE("GPL");
#ifdef DEBUG
MODULE_PARM(ntdebug, "i");
MODULE_PARM_DESC(ntdebug, "Debug level");
#endif

module_init(init_ntfs_fs)
module_exit(exit_ntfs_fs)


:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.027 ]--