Example #1
0
File: fs.c Project: hugh712/Jollen
/* 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?
}
Example #2
0
static int ntfs_fill_super(struct super_block *s, void *options, int silent)
{
        struct buffer_head *bh0, *bh1, *bh2;
        struct ntfs_boot_block *bootblock;
        struct ntfs_super_block *superblock;
        struct ntfs_spare_block *spareblock;
        struct ntfs_sb_info *sbi;
        struct inode *root;

        kuid_t uid;
        kgid_t gid;
        umode_t umask;
        int lowercase, eas, chk, errs, chkdsk, timeshift;

        dnode_secno root_dno;
        struct ntfs_dirent *de = NULL;
        struct quad_buffer_head qbh;

        int o;

        save_mount_options(s, options);

        sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
        if (!sbi) {
                return -ENOMEM;
        }
        s->s_fs_info = sbi;

        sbi->sb_bmp_dir = NULL;
        sbi->sb_cp_table = NULL;

        mutex_init(&sbi->ntfs_mutex);
        ntfs_lock(s);

        uid = current_uid();
        gid = current_gid();
        umask = current_umask();
        lowercase = 0;
        eas = 2;
        chk = 1;
        errs = 1;
        chkdsk = 1;
        timeshift = 0;

        if (!(o = parse_opts(options, &uid, &gid, &umask, &lowercase,
            &eas, &chk, &errs, &chkdsk, &timeshift))) {
                printk("NTFS: bad mount options.\n");
                goto bail0;
        }
        if (o==2) {
                ntfs_help();
                goto bail0;
        }

        /*sbi->sb_mounting = 1;*/
        sb_set_blocksize(s, 512);
        sbi->sb_fs_size = -1;
        if (!(bootblock = ntfs_map_sector(s, 0, &bh0, 0))) goto bail1;
        if (!(superblock = ntfs_map_sector(s, 16, &bh1, 1))) goto bail2;
        if (!(spareblock = ntfs_map_sector(s, 17, &bh2, 0))) goto bail3;

        /* Check magics */
        if (/*le16_to_cpu(bootblock->magic) != BB_MAGIC
            ||*/ le32_to_cpu(superblock->magic) != SB_MAGIC
            || le32_to_cpu(spareblock->magic) != SP_MAGIC) {
                if (!silent) printk("NTFS: Bad magic ... probably not NTFS\n");
                goto bail4;
        }

        /* Check version */
        if (!(s->s_flags & MS_RDONLY) &&
              superblock->funcversion != 2 && superblock->funcversion != 3) {
                printk("NTFS: Bad version %d,%d. Mount readonly to go around\n",
                        (int)superblock->version, (int)superblock->funcversion);
                printk("NTFS: please try recent version of NTFS driver at http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/ntfs/index-e.cgi and if it still can't understand this format, contact author - [email protected]\n");
                goto bail4;
        }

        s->s_flags |= MS_NOATIME;

        /* Fill superblock stuff */
        s->s_magic = NTFS_SUPER_MAGIC;
        s->s_op = &ntfs_sops;
        s->s_d_op = &ntfs_dentry_operations;

        sbi->sb_root = le32_to_cpu(superblock->root);
        sbi->sb_fs_size = le32_to_cpu(superblock->n_sectors);
        sbi->sb_bitmaps = le32_to_cpu(superblock->bitmaps);
        sbi->sb_dirband_start = le32_to_cpu(superblock->dir_band_start);
        sbi->sb_dirband_size = le32_to_cpu(superblock->n_dir_band);
        sbi->sb_dmap = le32_to_cpu(superblock->dir_band_bitmap);
        sbi->sb_uid = uid;
        sbi->sb_gid = gid;
        sbi->sb_mode = 0777 & ~umask;
        sbi->sb_n_free = -1;
        sbi->sb_n_free_dnodes = -1;
        sbi->sb_lowercase = lowercase;
        sbi->sb_eas = eas;
        sbi->sb_chk = chk;
        sbi->sb_chkdsk = chkdsk;
        sbi->sb_err = errs;
        sbi->sb_timeshift = timeshift;
        sbi->sb_was_error = 0;
        sbi->sb_cp_table = NULL;
        sbi->sb_c_bitmap = -1;
        sbi->sb_max_fwd_alloc = 0xffffff;

        if (sbi->sb_fs_size >= 0x80000000) {
                ntfs_error(s, "invalid size in superblock: %08x",
                        (unsigned)sbi->sb_fs_size);
                goto bail4;
        }

        /* Load bitmap directory */
        if (!(sbi->sb_bmp_dir = ntfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps))))
                goto bail4;

        /* Check for general fs errors*/
        if (spareblock->dirty && !spareblock->old_wrote) {
                if (errs == 2) {
                        printk("NTFS: Improperly stopped, not mounted\n");
                        goto bail4;
                }
                ntfs_error(s, "improperly stopped");
        }

        if (!(s->s_flags & MS_RDONLY)) {
                spareblock->dirty = 1;
                spareblock->old_wrote = 0;
                mark_buffer_dirty(bh2);
        }

        if (spareblock->hotfixes_used || spareblock->n_spares_used) {
                if (errs >= 2) {
                        printk("NTFS: Hotfixes not supported here, try chkdsk\n");
                        mark_dirty(s, 0);
                        goto bail4;
                }
                ntfs_error(s, "hotfixes not supported here, try chkdsk");
                if (errs == 0) printk("NTFS: Proceeding, but your filesystem will be probably corrupted by this driver...\n");
                else printk("NTFS: This driver may read bad files or crash when operating on disk with hotfixes.\n");
        }
        if (le32_to_cpu(spareblock->n_dnode_spares) != le32_to_cpu(spareblock->n_dnode_spares_free)) {
                if (errs >= 2) {
                        printk("NTFS: Spare dnodes used, try chkdsk\n");
                        mark_dirty(s, 0);
                        goto bail4;
                }
                ntfs_error(s, "warning: spare dnodes used, try chkdsk");
                if (errs == 0) printk("NTFS: Proceeding, but your filesystem could be corrupted if you delete files or directories\n");
        }
        if (chk) {
                unsigned a;
                if (le32_to_cpu(superblock->dir_band_end) - le32_to_cpu(superblock->dir_band_start) + 1 != le32_to_cpu(superblock->n_dir_band) ||
                    le32_to_cpu(superblock->dir_band_end) < le32_to_cpu(superblock->dir_band_start) || le32_to_cpu(superblock->n_dir_band) > 0x4000) {
                        ntfs_error(s, "dir band size mismatch: dir_band_start==%08x, dir_band_end==%08x, n_dir_band==%08x",
                                le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->dir_band_end), le32_to_cpu(superblock->n_dir_band));
                        goto bail4;
                }
                a = sbi->sb_dirband_size;
                sbi->sb_dirband_size = 0;
                if (ntfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_start), le32_to_cpu(superblock->n_dir_band), "dir_band") ||
                    ntfs_chk_sectors(s, le32_to_cpu(superblock->dir_band_bitmap), 4, "dir_band_bitmap") ||
                    ntfs_chk_sectors(s, le32_to_cpu(superblock->bitmaps), 4, "bitmaps")) {
                        mark_dirty(s, 0);
                        goto bail4;
                }
                sbi->sb_dirband_size = a;
        } else printk("NTFS: You really don't want any checks? You are crazy...\n");

        /* Load code page table */
        if (le32_to_cpu(spareblock->n_code_pages))
                if (!(sbi->sb_cp_table = ntfs_load_code_page(s, le32_to_cpu(spareblock->code_page_dir))))
                        printk("NTFS: Warning: code page support is disabled\n");

        brelse(bh2);
        brelse(bh1);
        brelse(bh0);

        root = iget_locked(s, sbi->sb_root);
        if (!root)
                goto bail0;
        ntfs_init_inode(root);
        ntfs_read_inode(root);
        unlock_new_inode(root);
        s->s_root = d_make_root(root);
        if (!s->s_root)
                goto bail0;

        /*
         * find the root directory's . pointer & finish filling in the inode
         */

        root_dno = ntfs_fnode_dno(s, sbi->sb_root);
        if (root_dno)
                de = map_dirent(root, root_dno, "\001\001", 2, NULL, &qbh);
        if (!de)
                ntfs_error(s, "unable to find root dir");
        else {
                root->i_atime.tv_sec = local_to_gmt(s, le32_to_cpu(de->read_date));
                root->i_atime.tv_nsec = 0;
                root->i_mtime.tv_sec = local_to_gmt(s, le32_to_cpu(de->write_date));
                root->i_mtime.tv_nsec = 0;
                root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));
                root->i_ctime.tv_nsec = 0;
                ntfs_i(root)->i_ea_size = le32_to_cpu(de->ea_size);
                ntfs_i(root)->i_parent_dir = root->i_ino;
                if (root->i_size == -1)
                        root->i_size = 2048;
                if (root->i_blocks == -1)
                        root->i_blocks = 5;
                ntfs_brelse4(&qbh);
        }
        ntfs_unlock(s);
        return 0;

bail4:  brelse(bh2);
bail3:  brelse(bh1);
bail2:  brelse(bh0);
bail1:
bail0:
        ntfs_unlock(s);
        kfree(sbi->sb_bmp_dir);
        kfree(sbi->sb_cp_table);
        s->s_fs_info = NULL;
        kfree(sbi);
        return -EINVAL;
}
Example #3
0
/* 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;
	int can_mmap=0;
	ntfs_inode *ino;
	ntfs_attribute *data;
	ntfs_attribute *si;

	vol=NTFS_INO2VOL(inode);
	inode->i_mode=0;
	ntfs_debug(DEBUG_OTHER, "ntfs_read_inode %x\n",(unsigned)inode->i_ino);

	switch(inode->i_ino)
	{
		/* those are loaded special files */
	case FILE_MFT:
		ntfs_error("Trying to open MFT\n");return;
	default:
		#ifdef NTFS_IN_LINUX_KERNEL
		ino=&inode->u.ntfs_i;
		#else
		/* FIXME: check for ntfs_malloc failure */
		ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
		inode->u.generic_ip=ino;
		#endif
		if(!ino || ntfs_init_inode(ino,
					   NTFS_INO2VOL(inode),inode->i_ino))
		{
			ntfs_debug(DEBUG_OTHER, "NTFS:Error loading inode %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;
		can_mmap=0;
	}
	else
	{
		inode->i_size=data->size;
		/* FIXME: once ntfs_get_block is implemented, uncomment the
		 * next line and remove the can_mmap = 0; */
		/* can_mmap=!data->resident && !data->compressed;*/
		can_mmap = 0;
	}
	/* 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
	{
		/* As long as ntfs_get_block() is just a call to BUG() do not
	 	 * define any [bm]map ops or we get the BUG() whenever someone
		 * runs mc or mpg123 on an ntfs partition!
		 * FIXME: Uncomment the below code when ntfs_get_block is
		 * implemented. */
		/* if (can_mmap) {
			inode->i_op = &ntfs_inode_operations;
			inode->i_fop = &ntfs_file_operations;
			inode->i_mapping->a_ops = &ntfs_aops;
			inode->u.ntfs_i.mmu_private = inode->i_size;
		} else */ {
			inode->i_op=&ntfs_inode_operations_nobmap;
			inode->i_fop=&ntfs_file_operations_nommap;
		}
		inode->i_mode=S_IFREG|S_IRUGO;
	}
#ifdef CONFIG_NTFS_RW
	if(!data || !data->compressed)
		inode->i_mode|=S_IWUGO;
#endif
	inode->i_mode &= ~vol->umask;
}
Example #4
0
/* 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;
	int can_mmap=0;
	ntfs_inode *ino;
	ntfs_attribute *data;
	ntfs_attribute *si;

	vol=NTFS_INO2VOL(inode);
	inode->i_op=NULL;
	inode->i_mode=0;
	ntfs_debug(DEBUG_OTHER, "ntfs_read_inode %x\n",(unsigned)inode->i_ino);

	switch(inode->i_ino)
	{
		/* those are loaded special files */
	case FILE_MFT:
		ntfs_error("Trying to open MFT\n");return;
	default:
		#ifdef NTFS_IN_LINUX_KERNEL
		ino=&inode->u.ntfs_i;
		#else
		/* FIXME: check for ntfs_malloc failure */
		ino=(ntfs_inode*)ntfs_malloc(sizeof(ntfs_inode));
		inode->u.generic_ip=ino;
		#endif
		if(!ino || ntfs_init_inode(ino,
					   NTFS_INO2VOL(inode),inode->i_ino))
		{
			ntfs_debug(DEBUG_OTHER, "NTFS:Error loading inode %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;
		can_mmap=0;
	}
	else
	{
		inode->i_size=data->size;
		can_mmap=!data->resident && !data->compressed;
	}
	/* 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_mode=S_IFDIR|S_IRUGO|S_IXUGO;
	}
	else
	{
		inode->i_op=can_mmap ? &ntfs_inode_operations : 
			&ntfs_inode_operations_nobmap;
		inode->i_mode=S_IFREG|S_IRUGO;
	}
#ifdef CONFIG_NTFS_RW
	if(!data || !data->compressed)
		inode->i_mode|=S_IWUGO;
#endif
	inode->i_mode &= ~vol->umask;
}
Example #5
0
static int ntfs_symlink(struct inode *dir, struct dentry *dentry, const char *symlink)
{
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct buffer_head *bh;
        struct fnode *fnode;
        fnode_secno fno;
        int r;
        struct ntfs_dirent dee;
        struct inode *result;
        int err;
        if ((err = ntfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
        ntfs_lock(dir->i_sb);
        if (ntfs_sb(dir->i_sb)->sb_eas < 2) {
                ntfs_unlock(dir->i_sb);
                return -EPERM;
        }
        err = -ENOSPC;
        fnode = ntfs_alloc_fnode(dir->i_sb, ntfs_i(dir)->i_dno, &fno, &bh);
        if (!fnode)
                goto bail;
        memset(&dee, 0, sizeof dee);
        dee.archive = 1;
        dee.hidden = name[0] == '.';
        dee.fnode = cpu_to_le32(fno);
        dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));

        result = new_inode(dir->i_sb);
        if (!result)
                goto bail1;
        result->i_ino = fno;
        ntfs_init_inode(result);
        ntfs_i(result)->i_parent_dir = dir->i_ino;
        result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_nsec = 0;
        ntfs_i(result)->i_ea_size = 0;
        result->i_mode = S_IFLNK | 0777;
        result->i_uid = current_fsuid();
        result->i_gid = current_fsgid();
        result->i_blocks = 1;
        set_nlink(result, 1);
        result->i_size = strlen(symlink);
        result->i_op = &page_symlink_inode_operations;
        result->i_data.a_ops = &ntfs_symlink_aops;

        r = ntfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail2;
        if (r == -1) {
                err = -EEXIST;
                goto bail2;
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
        fnode->up = cpu_to_le32(dir->i_ino);
        ntfs_set_ea(result, fnode, "SYMLINK", symlink, strlen(symlink));
        mark_buffer_dirty(bh);
        brelse(bh);

        insert_inode_hash(result);

        ntfs_write_inode_nolock(result);
        d_instantiate(dentry, result);
        ntfs_unlock(dir->i_sb);
        return 0;
bail2:
        iput(result);
bail1:
        brelse(bh);
        ntfs_free_sectors(dir->i_sb, fno, 1);
bail:
        ntfs_unlock(dir->i_sb);
        return err;
}
Example #6
0
static int ntfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct quad_buffer_head qbh0;
        struct buffer_head *bh;
        struct ntfs_dirent *de;
        struct fnode *fnode;
        struct dnode *dnode;
        struct inode *result;
        fnode_secno fno;
        dnode_secno dno;
        int r;
        struct ntfs_dirent dee;
        int err;
        if ((err = ntfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
        ntfs_lock(dir->i_sb);
        err = -ENOSPC;
        fnode = ntfs_alloc_fnode(dir->i_sb, ntfs_i(dir)->i_dno, &fno, &bh);
        if (!fnode)
                goto bail;
        dnode = ntfs_alloc_dnode(dir->i_sb, fno, &dno, &qbh0);
        if (!dnode)
                goto bail1;
        memset(&dee, 0, sizeof dee);
        dee.directory = 1;
        if (!(mode & 0222)) dee.read_only = 1;
        /*dee.archive = 0;*/
        dee.hidden = name[0] == '.';
        dee.fnode = cpu_to_le32(fno);
        dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
        result = new_inode(dir->i_sb);
        if (!result)
                goto bail2;
        ntfs_init_inode(result);
        result->i_ino = fno;
        ntfs_i(result)->i_parent_dir = dir->i_ino;
        ntfs_i(result)->i_dno = dno;
        result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_nsec = 0;
        ntfs_i(result)->i_ea_size = 0;
        result->i_mode |= S_IFDIR;
        result->i_op = &ntfs_dir_iops;
        result->i_fop = &ntfs_dir_ops;
        result->i_blocks = 4;
        result->i_size = 2048;
        set_nlink(result, 2);
        if (dee.read_only)
                result->i_mode &= ~0222;

        r = ntfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail3;
        if (r == -1) {
                err = -EEXIST;
                goto bail3;
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
        fnode->up = cpu_to_le32(dir->i_ino);
        fnode->flags |= FNODE_dir;
        fnode->btree.n_free_nodes = 7;
        fnode->btree.n_used_nodes = 1;
        fnode->btree.first_free = cpu_to_le16(0x14);
        fnode->u.external[0].disk_secno = cpu_to_le32(dno);
        fnode->u.external[0].file_secno = cpu_to_le32(-1);
        dnode->root_dnode = 1;
        dnode->up = cpu_to_le32(fno);
        de = ntfs_add_de(dir->i_sb, dnode, "\001\001", 2, 0);
        de->creation_date = de->write_date = de->read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));
        if (!(mode & 0222)) de->read_only = 1;
        de->first = de->directory = 1;
        /*de->hidden = de->system = 0;*/
        de->fnode = cpu_to_le32(fno);
        mark_buffer_dirty(bh);
        brelse(bh);
        ntfs_mark_4buffers_dirty(&qbh0);
        ntfs_brelse4(&qbh0);
        inc_nlink(dir);
        insert_inode_hash(result);

        if (!uid_eq(result->i_uid, current_fsuid()) ||
            !gid_eq(result->i_gid, current_fsgid()) ||
            result->i_mode != (mode | S_IFDIR)) {
                result->i_uid = current_fsuid();
                result->i_gid = current_fsgid();
                result->i_mode = mode | S_IFDIR;
                ntfs_write_inode_nolock(result);
        }
        d_instantiate(dentry, result);
        ntfs_unlock(dir->i_sb);
        return 0;
bail3:
        iput(result);
bail2:
        ntfs_brelse4(&qbh0);
        ntfs_free_dnode(dir->i_sb, dno);
bail1:
        brelse(bh);
        ntfs_free_sectors(dir->i_sb, fno, 1);
bail:
        ntfs_unlock(dir->i_sb);
        return err;
}
Example #7
0
static int ntfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev)
{
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct buffer_head *bh;
        struct fnode *fnode;
        fnode_secno fno;
        int r;
        struct ntfs_dirent dee;
        struct inode *result = NULL;
        int err;
        if ((err = ntfs_chk_name(name, &len))) return err==-ENOENT ? -EINVAL : err;
        if (ntfs_sb(dir->i_sb)->sb_eas < 2) return -EPERM;
        if (!new_valid_dev(rdev))
                return -EINVAL;
        ntfs_lock(dir->i_sb);
        err = -ENOSPC;
        fnode = ntfs_alloc_fnode(dir->i_sb, ntfs_i(dir)->i_dno, &fno, &bh);
        if (!fnode)
                goto bail;
        memset(&dee, 0, sizeof dee);
        if (!(mode & 0222)) dee.read_only = 1;
        dee.archive = 1;
        dee.hidden = name[0] == '.';
        dee.fnode = cpu_to_le32(fno);
        dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));

        result = new_inode(dir->i_sb);
        if (!result)
                goto bail1;

        ntfs_init_inode(result);
        result->i_ino = fno;
        ntfs_i(result)->i_parent_dir = dir->i_ino;
        result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_nsec = 0;
        ntfs_i(result)->i_ea_size = 0;
        result->i_uid = current_fsuid();
        result->i_gid = current_fsgid();
        set_nlink(result, 1);
        result->i_size = 0;
        result->i_blocks = 1;
        init_special_inode(result, mode, rdev);

        r = ntfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail2;
        if (r == -1) {
                err = -EEXIST;
                goto bail2;
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
        fnode->up = cpu_to_le32(dir->i_ino);
        mark_buffer_dirty(bh);

        insert_inode_hash(result);

        ntfs_write_inode_nolock(result);
        d_instantiate(dentry, result);
        brelse(bh);
        ntfs_unlock(dir->i_sb);
        return 0;
bail2:
        iput(result);
bail1:
        brelse(bh);
        ntfs_free_sectors(dir->i_sb, fno, 1);
bail:
        ntfs_unlock(dir->i_sb);
        return err;
}
Example #8
0
static int ntfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
{
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
        struct inode *result = NULL;
        struct buffer_head *bh;
        struct fnode *fnode;
        fnode_secno fno;
        int r;
        struct ntfs_dirent dee;
        int err;
        if ((err = ntfs_chk_name(name, &len)))
                return err==-ENOENT ? -EINVAL : err;
        ntfs_lock(dir->i_sb);
        err = -ENOSPC;
        fnode = ntfs_alloc_fnode(dir->i_sb, ntfs_i(dir)->i_dno, &fno, &bh);
        if (!fnode)
                goto bail;
        memset(&dee, 0, sizeof dee);
        if (!(mode & 0222)) dee.read_only = 1;
        dee.archive = 1;
        dee.hidden = name[0] == '.';
        dee.fnode = cpu_to_le32(fno);
        dee.creation_date = dee.write_date = dee.read_date = cpu_to_le32(gmt_to_local(dir->i_sb, get_seconds()));

        result = new_inode(dir->i_sb);
        if (!result)
                goto bail1;

        ntfs_init_inode(result);
        result->i_ino = fno;
        result->i_mode |= S_IFREG;
        result->i_mode &= ~0111;
        result->i_op = &ntfs_file_iops;
        result->i_fop = &ntfs_file_ops;
        set_nlink(result, 1);
        ntfs_i(result)->i_parent_dir = dir->i_ino;
        result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, le32_to_cpu(dee.creation_date));
        result->i_ctime.tv_nsec = 0;
        result->i_mtime.tv_nsec = 0;
        result->i_atime.tv_nsec = 0;
        ntfs_i(result)->i_ea_size = 0;
        if (dee.read_only)
                result->i_mode &= ~0222;
        result->i_blocks = 1;
        result->i_size = 0;
        result->i_data.a_ops = &ntfs_aops;
        ntfs_i(result)->mmu_private = 0;

        r = ntfs_add_dirent(dir, name, len, &dee);
        if (r == 1)
                goto bail2;
        if (r == -1) {
                err = -EEXIST;
                goto bail2;
        }
        fnode->len = len;
        memcpy(fnode->name, name, len > 15 ? 15 : len);
        fnode->up = cpu_to_le32(dir->i_ino);
        mark_buffer_dirty(bh);
        brelse(bh);

        insert_inode_hash(result);

        if (!uid_eq(result->i_uid, current_fsuid()) ||
            !gid_eq(result->i_gid, current_fsgid()) ||
            result->i_mode != (mode | S_IFREG)) {
                result->i_uid = current_fsuid();
                result->i_gid = current_fsgid();
                result->i_mode = mode | S_IFREG;
                ntfs_write_inode_nolock(result);
        }
        d_instantiate(dentry, result);
        ntfs_unlock(dir->i_sb);
        return 0;

bail2:
        iput(result);
bail1:
        brelse(bh);
        ntfs_free_sectors(dir->i_sb, fno, 1);
bail:
        ntfs_unlock(dir->i_sb);
        return err;
}