ntfsrm has been split up and merged into libntfs.
currently it's #ifdef'd out. tree.c - code for handling directory trees rich.c - a few helpers without a home (this file will go away soon) Note: ntfsrm isn't in the build any more (you need to ./configure --enable-rich; make extras). When rm is less intrusive, again, I'll put it back in the build.edge.strict_endians
parent
139f6c6603
commit
2a8d602d9f
|
@ -149,6 +149,15 @@ AC_ARG_ENABLE(debug-logging,
|
|||
fi,
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(rich,
|
||||
AS_HELP_STRING(--enable-rich,enable Rich's "rm" test code), ,
|
||||
enable_rich=no
|
||||
)
|
||||
AM_CONDITIONAL(ENABLE_RICH, test "$enable_rich" = yes)
|
||||
if test "$enable_rich" = "yes"; then
|
||||
CFLAGS="$CFLAGS -DNTFS_RICH"
|
||||
fi
|
||||
|
||||
# Use GNU extensions if available.
|
||||
AC_GNU_SOURCE
|
||||
|
||||
|
|
|
@ -24,10 +24,12 @@ linux_ntfsinclude_HEADERS = \
|
|||
logging.h \
|
||||
mft.h \
|
||||
mst.h \
|
||||
ntfstime.h \
|
||||
rich.h \
|
||||
runlist.h \
|
||||
security.h \
|
||||
support.h \
|
||||
ntfstime.h \
|
||||
tree.h \
|
||||
types.h \
|
||||
unistr.h \
|
||||
version.h \
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* bitmap.h - Exports for bitmap handling. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2000-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -130,4 +131,36 @@ static __inline__ int ntfs_bitmap_clear_bit(ntfs_attr *na, s64 bit)
|
|||
return ntfs_bitmap_clear_run(na, bit, 1);
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include "layout.h"
|
||||
#include "inode.h"
|
||||
|
||||
/**
|
||||
* struct ntfs_bmp
|
||||
* a cache for either dir/$BITMAP, $MFT/$BITMAP or $Bitmap/$DATA
|
||||
*/
|
||||
struct ntfs_bmp {
|
||||
ntfs_volume *vol;
|
||||
ntfs_attr *attr;
|
||||
int count;
|
||||
u8 **data;
|
||||
VCN *data_vcn;
|
||||
};
|
||||
|
||||
|
||||
int ntfs_bmp_rollback (struct ntfs_bmp *bmp);
|
||||
int ntfs_bmp_commit (struct ntfs_bmp *bmp);
|
||||
void ntfs_bmp_free (struct ntfs_bmp *bmp);
|
||||
struct ntfs_bmp * ntfs_bmp_create (ntfs_inode *inode, ATTR_TYPES type, ntfschar *name, int name_len);
|
||||
int ntfs_bmp_add_data (struct ntfs_bmp *bmp, VCN vcn, u8 *data);
|
||||
u8 * ntfs_bmp_get_data (struct ntfs_bmp *bmp, VCN vcn);
|
||||
int ntfs_bmp_set_range (struct ntfs_bmp *bmp, VCN vcn, s64 length, int value);
|
||||
s64 ntfs_bmp_find_last_set (struct ntfs_bmp *bmp);
|
||||
int ntfs_bmp_find_space (struct ntfs_bmp *bmp, LCN start, long size);
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
#endif /* defined _NTFS_BITMAP_H */
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2002 Anton Altaparmakov
|
||||
* Copyright (c) 2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -73,5 +74,37 @@ typedef int (*ntfs_filldir_t)(void *dirent, const ntfschar *name,
|
|||
extern int ntfs_readdir(ntfs_inode *dir_ni, s64 *pos,
|
||||
void *dirent, ntfs_filldir_t filldir);
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
/**
|
||||
* struct ntfs_dir
|
||||
*/
|
||||
struct ntfs_dir {
|
||||
ntfs_volume *vol;
|
||||
struct ntfs_dir *parent;
|
||||
ntfschar *name;
|
||||
int name_len;
|
||||
MFT_REF mft_num;
|
||||
struct ntfs_dt *index;
|
||||
struct ntfs_dir **children;
|
||||
int child_count;
|
||||
struct ntfs_bmp *bitmap;
|
||||
ntfs_inode *inode;
|
||||
ntfs_attr *iroot;
|
||||
ntfs_attr *ialloc;
|
||||
int index_size;
|
||||
};
|
||||
|
||||
|
||||
int ntfs_dir_rollback (struct ntfs_dir *dir);
|
||||
int ntfs_dir_truncate (ntfs_volume *vol, struct ntfs_dir *dir);
|
||||
int ntfs_dir_commit (struct ntfs_dir *dir);
|
||||
void ntfs_dir_free (struct ntfs_dir *dir);
|
||||
struct ntfs_dir * ntfs_dir_create (ntfs_volume *vol, MFT_REF mft_num);
|
||||
void ntfs_dir_add (struct ntfs_dir *parent, struct ntfs_dir *child);
|
||||
struct ntfs_dir * ntfs_dir_find2 (struct ntfs_dir *dir, ntfschar *name, int name_len);
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
#endif /* defined _NTFS_DIR_H */
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2004 Anton Altaparmakov
|
||||
* Copyright (c) 2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -121,4 +122,21 @@ static inline void ntfs_index_entry_mark_dirty(ntfs_index_context *ictx)
|
|||
ictx->ia_dirty = TRUE;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include "layout.h"
|
||||
|
||||
void ntfs_ie_free (INDEX_ENTRY *ie);
|
||||
INDEX_ENTRY * ntfs_ie_create (void);
|
||||
VCN ntfs_ie_get_vcn (INDEX_ENTRY *ie);
|
||||
INDEX_ENTRY * ntfs_ie_copy (INDEX_ENTRY *ie);
|
||||
INDEX_ENTRY * ntfs_ie_set_vcn (INDEX_ENTRY *ie, VCN vcn);
|
||||
INDEX_ENTRY * ntfs_ie_remove_vcn (INDEX_ENTRY *ie);
|
||||
INDEX_ENTRY * ntfs_ie_set_name (INDEX_ENTRY *ie, ntfschar *name, int namelen, FILE_NAME_TYPE_FLAGS nametype);
|
||||
INDEX_ENTRY * ntfs_ie_remove_name (INDEX_ENTRY *ie);
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
#endif /* _NTFS_INDEX_H */
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2001,2002 Anton Altaparmakov
|
||||
* Copyright (c) 2004-2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -184,4 +185,12 @@ extern int ntfs_inode_add_attrlist(ntfs_inode *ni);
|
|||
|
||||
extern int ntfs_inode_free_space(ntfs_inode *ni, int size);
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
int ntfs_inode_close2 (ntfs_inode *ni);
|
||||
ntfs_inode * ntfs_inode_open2 (ntfs_volume *vol, const MFT_REF mref);
|
||||
ntfs_inode * ntfs_inode_open3 (ntfs_volume *vol, const MFT_REF mref);
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
#endif /* defined _NTFS_INODE_H */
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
* mft.h - Exports for MFT record handling. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2000-2002 Anton Altaparmakov
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -110,5 +111,18 @@ extern ntfs_inode *ntfs_mft_record_alloc(ntfs_volume *vol, ntfs_inode *base_ni);
|
|||
|
||||
extern int ntfs_mft_record_free(ntfs_volume *vol, ntfs_inode *ni);
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "dir.h"
|
||||
|
||||
int ntfs_mft_remove_attr (struct ntfs_bmp *bmp, ntfs_inode *inode, ATTR_TYPES type);
|
||||
ATTR_RECORD * ntfs_mft_add_attr (ntfs_inode *inode, ATTR_TYPES type, u8 *data, int data_len);
|
||||
int ntfs_mft_resize_resident (ntfs_inode *inode, ATTR_TYPES type, ntfschar *name, int name_len, u8 *data, int data_len);
|
||||
int ntfs_mft_free_space (struct ntfs_dir *dir);
|
||||
int ntfs_mft_add_index (struct ntfs_dir *dir);
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
#endif /* defined _NTFS_MFT_H */
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* rich.h - Temporary junk file. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (in the main directory of the Linux-NTFS
|
||||
* distribution in the file COPYING); if not, write to the Free Software
|
||||
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _NTFS_RICH_H_
|
||||
#define _NTFS_RICH_H_
|
||||
|
||||
#include "layout.h"
|
||||
#include "attrib.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
// XXX Temporarily copied from utils.h
|
||||
#define RED "\e[31m"
|
||||
#define GREEN "\e[32m"
|
||||
#define YELLOW "\e[33m"
|
||||
#define BLUE "\e[34m"
|
||||
#define MAGENTA "\e[35m"
|
||||
#define CYAN "\e[36m"
|
||||
#define BOLD "\e[01m"
|
||||
#define END "\e[0m"
|
||||
|
||||
#define ROUND_UP(num,bound) (((num)+((bound)-1)) & ~((bound)-1))
|
||||
#define ROUND_DOWN(num,bound) ((num) & ~((bound)-1))
|
||||
#define ATTR_SIZE(s) ROUND_UP(s,8)
|
||||
|
||||
ATTR_RECORD * find_attribute (const ATTR_TYPES type, ntfs_attr_search_ctx *ctx);
|
||||
ATTR_RECORD * find_first_attribute (const ATTR_TYPES type, MFT_RECORD *mft);
|
||||
int utils_free_non_residents3 (struct ntfs_bmp *bmp, ntfs_inode *inode, ATTR_RECORD *attr);
|
||||
int utils_free_non_residents2 (ntfs_inode *inode, struct ntfs_bmp *bmp);
|
||||
void ntfs_name_print (ntfschar *name, int name_len);
|
||||
|
||||
#endif /* _NTFS_RICH_H_ */
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/**
|
||||
* tree.h - Directory tree handling code. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (in the main directory of the Linux-NTFS
|
||||
* distribution in the file COPYING); if not, write to the Free Software
|
||||
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _NTFS_TREE_H_
|
||||
#define _NTFS_TREE_H_
|
||||
|
||||
#include "layout.h"
|
||||
#include "volume.h"
|
||||
|
||||
struct ntfs_dir;
|
||||
|
||||
/**
|
||||
* struct ntfs_dt
|
||||
*/
|
||||
struct ntfs_dt {
|
||||
struct ntfs_dir *dir;
|
||||
struct ntfs_dt *parent;
|
||||
u8 *data;
|
||||
int data_len;
|
||||
int child_count;
|
||||
INDEX_ENTRY **children;
|
||||
struct ntfs_dt **sub_nodes;
|
||||
ntfs_inode **inodes;
|
||||
VCN vcn;
|
||||
INDEX_HEADER *header;
|
||||
BOOL changed;
|
||||
};
|
||||
|
||||
|
||||
void ntfs_dt_free (struct ntfs_dt *dt);
|
||||
int ntfs_dt_rollback (struct ntfs_dt *dt);
|
||||
int ntfs_dt_commit (struct ntfs_dt *dt);
|
||||
BOOL ntfs_dt_create_children2 (struct ntfs_dt *dt, int count);
|
||||
BOOL ntfs_dt_resize_children3 (struct ntfs_dt *dt, int new);
|
||||
int ntfs_dt_root_count (struct ntfs_dt *dt);
|
||||
int ntfs_dt_alloc_count (struct ntfs_dt *dt);
|
||||
int ntfs_dt_initialise2 (ntfs_volume *vol, struct ntfs_dt *dt);
|
||||
struct ntfs_dt * ntfs_dt_create (struct ntfs_dir *dir, struct ntfs_dt *parent, VCN vcn);
|
||||
MFT_REF ntfs_dt_find (struct ntfs_dt *dt, ntfschar *name, int name_len);
|
||||
struct ntfs_dt * ntfs_dt_find2 (struct ntfs_dt *dt, ntfschar *name, int name_len, int *index_num);
|
||||
struct ntfs_dt * ntfs_dt_find3 (struct ntfs_dt *dt, ntfschar *name, int name_len, int *index_num);
|
||||
struct ntfs_dt * ntfs_dt_find4 (struct ntfs_dt *dt, ntfschar *name, int name_len, int *index_num);
|
||||
void ntfs_dt_find_all (struct ntfs_dt *dt);
|
||||
int ntfs_dt_find_parent (struct ntfs_dt *dt);
|
||||
BOOL ntfs_dt_isroot (struct ntfs_dt *dt);
|
||||
int ntfs_dt_root_freespace (struct ntfs_dt *dt);
|
||||
int ntfs_dt_alloc_freespace (struct ntfs_dt *dt);
|
||||
int ntfs_dt_transfer (struct ntfs_dt *old, struct ntfs_dt *new, int start, int count);
|
||||
int ntfs_dt_alloc_insert (struct ntfs_dt *dt, INDEX_ENTRY *first, int count);
|
||||
INDEX_ENTRY * ntfs_dt_alloc_insert2 (struct ntfs_dt *dt, int before, int count, int bytes);
|
||||
int ntfs_dt_root_insert (struct ntfs_dt *dt, INDEX_ENTRY *first, int count);
|
||||
int ntfs_dt_alloc_remove2 (struct ntfs_dt *dt, int start, int count);
|
||||
int ntfs_dt_root_remove2 (struct ntfs_dt *dt, int start, int count);
|
||||
int ntfs_dt_transfer2 (struct ntfs_dt *old, struct ntfs_dt *new, int start, int count);
|
||||
int ntfs_dt_root_replace (struct ntfs_dt *del, int del_num, INDEX_ENTRY *del_ie, INDEX_ENTRY *suc_ie);
|
||||
BOOL ntfs_dt_alloc_replace (struct ntfs_dt *del, int del_num, INDEX_ENTRY *del_ie, INDEX_ENTRY *suc_ie);
|
||||
BOOL ntfs_dt_root_remove (struct ntfs_dt *del, int del_num);
|
||||
BOOL ntfs_dt_alloc_remove (struct ntfs_dt *del, int del_num);
|
||||
int ntfs_dt_alloc_add (struct ntfs_dt *parent, int index_num, INDEX_ENTRY *ie, struct ntfs_dt *child);
|
||||
int ntfs_dt_root_add (struct ntfs_dt *parent, int index_num, INDEX_ENTRY *ie, struct ntfs_dt *child);
|
||||
int ntfs_dt_add2 (INDEX_ENTRY *ie, struct ntfs_dt *suc, int suc_num, struct ntfs_dt *ded);
|
||||
|
||||
#endif /* _NTFS_TREE_H_ */
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2000-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -203,5 +204,16 @@ extern int ntfs_logfile_reset(ntfs_volume *vol);
|
|||
|
||||
extern int ntfs_volume_write_flags(ntfs_volume *v, const u16 flags);
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
int ntfs_volume_commit (ntfs_volume *vol);
|
||||
int ntfs_volume_rollback (ntfs_volume *vol);
|
||||
int ntfs_volume_umount2 (ntfs_volume *vol, const BOOL force);
|
||||
ntfs_volume * ntfs_volume_mount2 (const char *device, unsigned long flags, BOOL force);
|
||||
int utils_valid_device (const char *name, int force);
|
||||
ntfs_volume * utils_mount_volume (const char *device, unsigned long flags, BOOL force);
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
#endif /* defined _NTFS_VOLUME_H */
|
||||
|
||||
|
|
|
@ -60,6 +60,10 @@ libntfs_la_SOURCES = \
|
|||
version.c \
|
||||
volume.c
|
||||
|
||||
if ENABLE_RICH
|
||||
libntfs_la_SOURCES += rich.c tree.c
|
||||
endif
|
||||
|
||||
if ENABLE_GNOME_VFS
|
||||
|
||||
gnomevfsmoduleslibdir = $(libdir)/gnome-vfs-2.0/modules
|
||||
|
|
386
libntfs/bitmap.c
386
libntfs/bitmap.c
|
@ -2,6 +2,7 @@
|
|||
* bitmap.c - Bitmap handling code. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2002-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -220,3 +221,388 @@ int ntfs_bitmap_clear_run(ntfs_attr *na, s64 start_bit, s64 count)
|
|||
{
|
||||
return ntfs_bitmap_set_bits_in_run(na, start_bit, count, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "layout.h"
|
||||
#include "volume.h"
|
||||
#include "bitmap.h"
|
||||
#include "rich.h"
|
||||
|
||||
/**
|
||||
* ntfs_bmp_rollback
|
||||
*/
|
||||
int ntfs_bmp_rollback (struct ntfs_bmp *bmp)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((!bmp) || (bmp->count == 0))
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < bmp->count; i++)
|
||||
free (bmp->data[i]);
|
||||
|
||||
free (bmp->data);
|
||||
free (bmp->data_vcn);
|
||||
bmp->data = NULL;
|
||||
bmp->data_vcn = NULL;
|
||||
bmp->count = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_commit
|
||||
*/
|
||||
int ntfs_bmp_commit (struct ntfs_bmp *bmp)
|
||||
{
|
||||
int i;
|
||||
u32 cs;
|
||||
#ifdef RM_WRITE
|
||||
u32 ws; // write size
|
||||
#endif
|
||||
|
||||
if (!bmp)
|
||||
return 0;
|
||||
if (bmp->count == 0)
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
printf ("attr = 0x%02X\n", bmp->attr->type);
|
||||
printf ("resident = %d\n", !NAttrNonResident (bmp->attr));
|
||||
printf ("\ta size = %lld\n", bmp->attr->allocated_size);
|
||||
printf ("\td size = %lld\n", bmp->attr->data_size);
|
||||
printf ("\ti size = %lld\n", bmp->attr->initialized_size);
|
||||
#endif
|
||||
|
||||
printf ("commit bmp inode %lld, 0x%02X (%sresident)\n", bmp->attr->ni->mft_no, bmp->attr->type, NAttrNonResident (bmp->attr) ? "non-" : "");
|
||||
|
||||
if (NAttrNonResident (bmp->attr)) {
|
||||
cs = bmp->vol->cluster_size;
|
||||
|
||||
// non-resident
|
||||
for (i = 0; i < bmp->count; i++) {
|
||||
#ifdef RM_WRITE
|
||||
if (((bmp->data_vcn[i]+1) * cs) < bmp->attr->data_size)
|
||||
ws = cs;
|
||||
else
|
||||
ws = bmp->attr->data_size & (cs - 1);
|
||||
//printf ("writing %d bytes\n", ws);
|
||||
ntfs_attr_pwrite (bmp->attr, bmp->data_vcn[i] * cs, ws, bmp->data[i]); // XXX retval
|
||||
#endif
|
||||
printf (RED "\tntfs_attr_pwrite (vcn %lld)\n" END, bmp->data_vcn[i]);
|
||||
}
|
||||
} else {
|
||||
// resident
|
||||
#ifdef RM_WRITE
|
||||
ntfs_attr_pwrite (bmp->attr, bmp->data_vcn[0], bmp->attr->data_size, bmp->data[0]); // XXX retval
|
||||
#endif
|
||||
printf (RED "\tntfs_attr_pwrite resident (%lld)\n" END, bmp->attr->data_size);
|
||||
}
|
||||
|
||||
ntfs_bmp_rollback (bmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_free
|
||||
*/
|
||||
void ntfs_bmp_free (struct ntfs_bmp *bmp)
|
||||
{
|
||||
if (!bmp)
|
||||
return;
|
||||
|
||||
ntfs_bmp_rollback (bmp);
|
||||
|
||||
ntfs_attr_close (bmp->attr);
|
||||
|
||||
free (bmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_create
|
||||
*/
|
||||
struct ntfs_bmp * ntfs_bmp_create (ntfs_inode *inode, ATTR_TYPES type, ntfschar *name, int name_len)
|
||||
{
|
||||
struct ntfs_bmp *bmp;
|
||||
ntfs_attr *attr;
|
||||
|
||||
if (!inode)
|
||||
return NULL;
|
||||
|
||||
attr = ntfs_attr_open (inode, type, name, name_len);
|
||||
if (!attr)
|
||||
return NULL;
|
||||
|
||||
bmp = calloc (1, sizeof (*bmp));
|
||||
if (!bmp) {
|
||||
ntfs_attr_close (attr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bmp->vol = inode->vol;
|
||||
bmp->attr = attr;
|
||||
bmp->data = NULL;
|
||||
bmp->data_vcn = NULL;
|
||||
bmp->count = 0;
|
||||
|
||||
return bmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_add_data
|
||||
*/
|
||||
int ntfs_bmp_add_data (struct ntfs_bmp *bmp, VCN vcn, u8 *data)
|
||||
{
|
||||
int i = 0;
|
||||
int old;
|
||||
int new;
|
||||
|
||||
if (!bmp || !data)
|
||||
return -1;
|
||||
|
||||
old = ROUND_UP (bmp->count, 16);
|
||||
bmp->count++;
|
||||
new = ROUND_UP (bmp->count, 16);
|
||||
|
||||
if (old != new) {
|
||||
bmp->data = realloc (bmp->data, new * sizeof (*bmp->data));
|
||||
bmp->data_vcn = realloc (bmp->data_vcn , new * sizeof (*bmp->data_vcn));
|
||||
}
|
||||
|
||||
for (i = 0; i < bmp->count-1; i++)
|
||||
if (bmp->data_vcn[i] > vcn)
|
||||
break;
|
||||
|
||||
if ((bmp->count-i) > 0) {
|
||||
memmove (&bmp->data[i+1], &bmp->data[i], (bmp->count-i) * sizeof (*bmp->data));
|
||||
memmove (&bmp->data_vcn[i+1], &bmp->data_vcn[i], (bmp->count-i) * sizeof (*bmp->data_vcn));
|
||||
}
|
||||
|
||||
bmp->data[i] = data;
|
||||
bmp->data_vcn[i] = vcn;
|
||||
|
||||
return bmp->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_get_data
|
||||
*/
|
||||
u8 * ntfs_bmp_get_data (struct ntfs_bmp *bmp, VCN vcn)
|
||||
{
|
||||
u8 *buffer;
|
||||
int i;
|
||||
int cs;
|
||||
int cb;
|
||||
|
||||
if (!bmp)
|
||||
return NULL;
|
||||
|
||||
cs = bmp->vol->cluster_size;
|
||||
cb = bmp->vol->cluster_size_bits;
|
||||
|
||||
// XXX range check against vol,attr
|
||||
// never compressed, so data = init
|
||||
|
||||
vcn >>= (cb + 3); // convert to bitmap clusters
|
||||
|
||||
for (i = 0; i < bmp->count; i++) {
|
||||
if (vcn == bmp->data_vcn[i]) {
|
||||
//printf ("reusing bitmap cluster %lld\n", vcn);
|
||||
return bmp->data[i];
|
||||
}
|
||||
}
|
||||
|
||||
buffer = calloc (1, cs); // XXX could be smaller if attr size < cluster size
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
//printf ("loading from bitmap cluster %lld\n", vcn);
|
||||
//printf ("loading from bitmap byte %lld\n", vcn<<cb);
|
||||
if (ntfs_attr_pread (bmp->attr, vcn<<cb, cs, buffer) < 0) {
|
||||
free (buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ntfs_bmp_add_data (bmp, vcn, buffer); // XXX retval
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_set_range
|
||||
*/
|
||||
int ntfs_bmp_set_range (struct ntfs_bmp *bmp, VCN vcn, s64 length, int value)
|
||||
{
|
||||
// shouldn't all the vcns be lcns?
|
||||
s64 i;
|
||||
u8 *buffer;
|
||||
int csib; // cluster size in bits
|
||||
|
||||
int block_start, block_finish; // rename to c[sf] (rename to clust_)
|
||||
int vcn_start, vcn_finish; // rename to v[sf]
|
||||
int byte_start, byte_finish; // rename to b[sf]
|
||||
u8 mask_start, mask_finish; // rename to m[sf]
|
||||
|
||||
s64 a,b;
|
||||
|
||||
if (!bmp)
|
||||
return -1;
|
||||
|
||||
if (value)
|
||||
value = 0xFF;
|
||||
|
||||
csib = bmp->vol->cluster_size << 3;
|
||||
|
||||
vcn_start = vcn;
|
||||
vcn_finish = vcn + length - 1;
|
||||
|
||||
//printf ("vcn_start = %d, vcn_finish = %d\n", vcn_start, vcn_finish);
|
||||
a = ROUND_DOWN (vcn_start, csib);
|
||||
b = ROUND_DOWN (vcn_finish, csib) + 1;
|
||||
|
||||
//printf ("a = %lld, b = %lld\n", a, b);
|
||||
|
||||
for (i = a; i < b; i += csib) {
|
||||
//printf ("ntfs_bmp_get_data %lld\n", i);
|
||||
buffer = ntfs_bmp_get_data (bmp, i);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
block_start = i;
|
||||
block_finish = block_start + csib - 1;
|
||||
|
||||
mask_start = (0xFF << (vcn_start & 7));
|
||||
mask_finish = (0xFF >> (7 - (vcn_finish & 7)));
|
||||
|
||||
if ((vcn_start >= block_start) && (vcn_start <= block_finish)) {
|
||||
byte_start = (vcn_start - block_start) >> 3;
|
||||
} else {
|
||||
byte_start = 0;
|
||||
mask_start = 0xFF;
|
||||
}
|
||||
|
||||
if ((vcn_finish >= block_start) && (vcn_finish <= block_finish)) {
|
||||
byte_finish = (vcn_finish - block_start) >> 3;
|
||||
} else {
|
||||
byte_finish = bmp->vol->cluster_size - 1;
|
||||
mask_finish = 0xFF;
|
||||
}
|
||||
|
||||
if ((byte_finish - byte_start) > 1) {
|
||||
memset (buffer+byte_start+1, value, byte_finish-byte_start-1);
|
||||
} else if (byte_finish == byte_start) {
|
||||
mask_start &= mask_finish;
|
||||
mask_finish = 0x00;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
buffer[byte_start] |= mask_start;
|
||||
buffer[byte_finish] |= mask_finish;
|
||||
} else {
|
||||
buffer[byte_start] &= (~mask_start);
|
||||
buffer[byte_finish] &= (~mask_finish);
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
printf (GREEN "Modified: inode %lld, ", bmp->attr->ni->mft_no);
|
||||
switch (bmp->attr->type) {
|
||||
case AT_BITMAP: printf ("$BITMAP"); break;
|
||||
case AT_DATA: printf ("$DATA"); break;
|
||||
default: break;
|
||||
}
|
||||
printf (" vcn %lld-%lld\n" END, vcn>>12, (vcn+length-1)>>12);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_find_last_set
|
||||
*/
|
||||
s64 ntfs_bmp_find_last_set (struct ntfs_bmp *bmp)
|
||||
{
|
||||
s64 clust_count;
|
||||
s64 byte_count;
|
||||
s64 clust;
|
||||
int byte;
|
||||
int bit;
|
||||
int note;
|
||||
u8 *buffer;
|
||||
|
||||
if (!bmp)
|
||||
return -2;
|
||||
|
||||
// find byte size of bmp
|
||||
// find cluster size of bmp
|
||||
|
||||
byte_count = bmp->attr->data_size;
|
||||
clust_count = ROUND_UP (byte_count, bmp->vol->cluster_size) >> bmp->vol->cluster_size_bits;
|
||||
|
||||
//printf ("bitmap = %lld bytes\n", byte_count);
|
||||
//printf ("bitmap = %lld buffers\n", clust_count);
|
||||
|
||||
// for each cluster backwards
|
||||
for (clust = clust_count-1; clust >= 0; clust--) {
|
||||
//printf ("cluster %lld\n", clust);
|
||||
//printf ("get vcn %lld\n", clust << (bmp->vol->cluster_size_bits + 3));
|
||||
buffer = ntfs_bmp_get_data (bmp, clust << (bmp->vol->cluster_size_bits + 3));
|
||||
//utils_dump_mem (buffer, 0, 8, DM_NO_ASCII);
|
||||
if (!buffer)
|
||||
return -2;
|
||||
if ((clust == (clust_count-1) && ((byte_count % bmp->vol->cluster_size) != 0))) {
|
||||
byte = byte_count % bmp->vol->cluster_size;
|
||||
} else {
|
||||
byte = bmp->vol->cluster_size;
|
||||
}
|
||||
//printf ("start byte = %d\n", byte);
|
||||
// for each byte backward
|
||||
for (byte--; byte >= 0; byte--) {
|
||||
//printf ("\tbyte %d (%d)\n", byte, buffer[byte]);
|
||||
// for each bit shift up
|
||||
note = -1;
|
||||
for (bit = 7; bit >= 0; bit--) {
|
||||
//printf ("\t\tbit %d (%d)\n", (1<<bit), buffer[byte] & (1<<bit));
|
||||
if (buffer[byte] & (1<<bit)) {
|
||||
// if set, keep note
|
||||
note = bit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (note >= 0) {
|
||||
// if note, return value
|
||||
//printf ("match %lld (c=%lld,b=%d,n=%d)\n", (((clust << bmp->vol->cluster_size_bits) + byte) << 3) + note, clust, byte, note);
|
||||
return ((((clust << bmp->vol->cluster_size_bits) + byte) << 3) + note);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_bmp_find_space
|
||||
*/
|
||||
int ntfs_bmp_find_space (struct ntfs_bmp *bmp, LCN start, long size)
|
||||
{
|
||||
if (!bmp)
|
||||
return 0;
|
||||
|
||||
start = 0;
|
||||
size = 0;
|
||||
|
||||
/*
|
||||
bmp find space - uncached bmp's
|
||||
$Bitmap/$DATA free space on volume
|
||||
dir/$BITMAP free index record
|
||||
$MFT/$BITMAP free record in mft
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
|
|
389
libntfs/dir.c
389
libntfs/dir.c
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2002-2005 Anton Altaparmakov
|
||||
* Copyright (c) 2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -1506,3 +1507,391 @@ err_out:
|
|||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "layout.h"
|
||||
#include "volume.h"
|
||||
#include "inode.h"
|
||||
#include "dir.h"
|
||||
#include "tree.h"
|
||||
#include "bitmap.h"
|
||||
#include "index.h"
|
||||
#include "rich.h"
|
||||
|
||||
/**
|
||||
* ntfs_dir_rollback
|
||||
*/
|
||||
int ntfs_dir_rollback (struct ntfs_dir *dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dir)
|
||||
return -1;
|
||||
|
||||
if (ntfs_dt_rollback (dir->index) < 0)
|
||||
return -1;
|
||||
|
||||
if (ntfs_bmp_rollback (dir->bitmap) < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < dir->child_count; i++) {
|
||||
if (ntfs_dir_rollback (dir->children[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_dir_truncate
|
||||
*/
|
||||
int ntfs_dir_truncate (ntfs_volume *vol, struct ntfs_dir *dir)
|
||||
{
|
||||
//int i;
|
||||
//u8 *buffer;
|
||||
//int buf_count;
|
||||
s64 last_bit;
|
||||
INDEX_ENTRY *ie;
|
||||
|
||||
if (!vol || !dir)
|
||||
return -1;
|
||||
|
||||
if ((dir->ialloc == NULL) || (dir->bitmap == NULL))
|
||||
return 0;
|
||||
|
||||
#if 0
|
||||
buf_count = ROUND_UP (dir->bitmap->attr->allocated_size, vol->cluster_size) >> vol->cluster_size_bits;
|
||||
printf ("alloc = %lld bytes\n", dir->ialloc->allocated_size);
|
||||
printf ("alloc = %lld clusters\n", dir->ialloc->allocated_size >> vol->cluster_size_bits);
|
||||
printf ("bitmap bytes 0 to %lld\n", ((dir->ialloc->allocated_size >> vol->cluster_size_bits)-1)>>3);
|
||||
printf ("bitmap = %p\n", dir->bitmap);
|
||||
printf ("bitmap = %lld bytes\n", dir->bitmap->attr->allocated_size);
|
||||
printf ("bitmap = %d buffers\n", buf_count);
|
||||
#endif
|
||||
|
||||
last_bit = ntfs_bmp_find_last_set (dir->bitmap);
|
||||
if (dir->ialloc->allocated_size == (dir->index_size * (last_bit + 1))) {
|
||||
//printf ("nothing to do\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf (BOLD YELLOW "Truncation needed\n" END);
|
||||
|
||||
#if 0
|
||||
printf ("\tlast bit = %lld\n", last_bit);
|
||||
printf ("\tactual IALLOC size = %lld\n", dir->ialloc->allocated_size);
|
||||
printf ("\tshould IALLOC size = %lld\n", dir->index_size * (last_bit + 1));
|
||||
#endif
|
||||
|
||||
if ((dir->index_size * (last_bit + 1)) == 0) {
|
||||
printf ("root dt %d, vcn = %lld\n", dir->index->changed, dir->index->vcn);
|
||||
//rollback all dts
|
||||
//ntfs_dt_rollback (dir->index);
|
||||
//dir->index = NULL;
|
||||
// What about the ROOT dt?
|
||||
|
||||
ie = ntfs_ie_copy (dir->index->children[0]);
|
||||
if (!ie) {
|
||||
printf (RED "IE copy failed\n" END);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ie = ntfs_ie_remove_vcn (ie);
|
||||
if (!ie) {
|
||||
printf (RED "IE remove vcn failed\n" END);
|
||||
return -1;
|
||||
}
|
||||
|
||||
//utils_dump_mem (dir->index->data, 0, dir->index->data_len, DM_DEFAULTS); printf ("\n");
|
||||
//utils_dump_mem (ie, 0, ie->length, DM_DEFAULTS); printf ("\n");
|
||||
ntfs_dt_root_replace (dir->index, 0, dir->index->children[0], ie);
|
||||
//utils_dump_mem (dir->index->data, 0, dir->index->data_len, DM_DEFAULTS); printf ("\n");
|
||||
//printf ("root dt %d, vcn = %lld\n", dir->index->changed, dir->index->vcn);
|
||||
|
||||
ntfs_ie_free (ie);
|
||||
ie = NULL;
|
||||
|
||||
//index flags remove LARGE_INDEX
|
||||
dir->index->header->flags = 0;
|
||||
|
||||
//rollback dir's bmp
|
||||
ntfs_bmp_free (dir->bitmap);
|
||||
dir->bitmap = NULL;
|
||||
|
||||
/*
|
||||
for (i = 0; i < dir->index->child_count; i++) {
|
||||
ntfs_dt_rollback (dir->index->sub_nodes[i]);
|
||||
dir->index->sub_nodes[i] = NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
//printf ("dir->index->inodes[0] = %p\n", dir->index->inodes[0]);
|
||||
|
||||
//remove 0xA0 attribute
|
||||
ntfs_mft_remove_attr (vol->private_bmp2, dir->inode, AT_INDEX_ALLOCATION);
|
||||
|
||||
//remove 0xB0 attribute
|
||||
ntfs_mft_remove_attr (vol->private_bmp2, dir->inode, AT_BITMAP);
|
||||
} else {
|
||||
printf (RED "Cannot shrink directory\n" END);
|
||||
//ntfs_dir_shrink_alloc
|
||||
//ntfs_dir_shrink_bitmap
|
||||
//make bitmap resident?
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove
|
||||
* dt -> dead
|
||||
* bitmap updated
|
||||
* rollback dead dts
|
||||
* commit bitmap
|
||||
* commit dts
|
||||
* commit dir
|
||||
*/
|
||||
/*
|
||||
* Reuse
|
||||
* search for lowest dead
|
||||
* update bitmap
|
||||
* init dt
|
||||
* remove from dead
|
||||
* insert into tree
|
||||
* init INDX
|
||||
*/
|
||||
|
||||
#if 0
|
||||
buffer = ntfs_bmp_get_data (dir->bitmap, 0);
|
||||
if (!buffer)
|
||||
return -1;
|
||||
|
||||
utils_dump_mem (buffer, 0, 8, DM_NO_ASCII);
|
||||
for (i = buf_count-1; i >= 0; i--) {
|
||||
if (buffer[i]) {
|
||||
printf ("alloc in use\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// <dir>/$BITMAP($I30)
|
||||
// <dir>/$INDEX_ALLOCATION($I30)
|
||||
// $Bitmap
|
||||
|
||||
// Find the highest set bit in the directory bitmap
|
||||
// can we free any clusters of the alloc?
|
||||
// if yes, resize attribute
|
||||
|
||||
// Are *any* bits set?
|
||||
// If not remove ialloc
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_dir_commit
|
||||
*/
|
||||
int ntfs_dir_commit (struct ntfs_dir *dir)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!dir)
|
||||
return 0;
|
||||
|
||||
printf ("commit dir inode %llu\n", dir->inode->mft_no);
|
||||
if (NInoDirty (dir->inode)) {
|
||||
#ifdef RM_WRITE
|
||||
ntfs_inode_sync (dir->inode);
|
||||
#endif
|
||||
printf (RED "\tntfs_inode_sync %llu\n" END, dir->inode->mft_no);
|
||||
}
|
||||
|
||||
if (ntfs_dt_commit (dir->index) < 0)
|
||||
return -1;
|
||||
|
||||
if (ntfs_bmp_commit (dir->bitmap) < 0)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < dir->child_count; i++) {
|
||||
if (ntfs_dir_commit (dir->children[i]) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_dir_free
|
||||
*/
|
||||
void ntfs_dir_free (struct ntfs_dir *dir)
|
||||
{
|
||||
struct ntfs_dir *parent;
|
||||
int i;
|
||||
|
||||
if (!dir)
|
||||
return;
|
||||
|
||||
ntfs_dir_rollback (dir);
|
||||
|
||||
parent = dir->parent;
|
||||
if (parent) {
|
||||
for (i = 0; i < parent->child_count; i++) {
|
||||
if (parent->children[i] == dir) {
|
||||
parent->children[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ntfs_attr_close (dir->iroot);
|
||||
ntfs_attr_close (dir->ialloc);
|
||||
ntfs_inode_close2 (dir->inode);
|
||||
|
||||
ntfs_dt_free (dir->index);
|
||||
ntfs_bmp_free (dir->bitmap);
|
||||
|
||||
for (i = 0; i < dir->child_count; i++)
|
||||
ntfs_dir_free (dir->children[i]);
|
||||
|
||||
free (dir->name);
|
||||
free (dir->children);
|
||||
free (dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_dir_create
|
||||
*/
|
||||
struct ntfs_dir * ntfs_dir_create (ntfs_volume *vol, MFT_REF mft_num)
|
||||
{
|
||||
struct ntfs_dir *dir = NULL;
|
||||
ntfs_inode *inode = NULL;
|
||||
ATTR_RECORD *rec = NULL;
|
||||
INDEX_ROOT *ir = NULL;
|
||||
FILE_NAME_ATTR *name = NULL;
|
||||
|
||||
if (!vol)
|
||||
return NULL;
|
||||
|
||||
//printf ("ntfs_dir_create %lld\n", MREF (mft_num));
|
||||
inode = ntfs_inode_open2 (vol, mft_num);
|
||||
if (!inode)
|
||||
return NULL;
|
||||
|
||||
dir = calloc (1, sizeof (*dir));
|
||||
if (!dir) {
|
||||
ntfs_inode_close2 (inode);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->inode = inode;
|
||||
dir->iroot = ntfs_attr_open (inode, AT_INDEX_ROOT, I30, 4);
|
||||
dir->ialloc = ntfs_attr_open (inode, AT_INDEX_ALLOCATION, I30, 4);
|
||||
|
||||
if (!dir->iroot) {
|
||||
ntfs_dir_free (dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dir->vol = vol;
|
||||
dir->parent = NULL;
|
||||
dir->name = NULL;
|
||||
dir->name_len = 0;
|
||||
dir->index = NULL;
|
||||
dir->children = NULL;
|
||||
dir->child_count = 0;
|
||||
dir->mft_num = mft_num;
|
||||
|
||||
// This may not exist
|
||||
dir->bitmap = ntfs_bmp_create (inode, AT_BITMAP, I30, 4);
|
||||
|
||||
if (dir->iroot) {
|
||||
rec = find_first_attribute (AT_INDEX_ROOT, inode->mrec);
|
||||
ir = (INDEX_ROOT*) ((u8*)rec + rec->value_offset);
|
||||
dir->index_size = ir->index_block_size;
|
||||
} else {
|
||||
// XXX !iroot?
|
||||
dir->index_size = 0;
|
||||
}
|
||||
|
||||
// Finally, find the dir's name
|
||||
rec = find_first_attribute (AT_FILE_NAME, inode->mrec);
|
||||
name = (FILE_NAME_ATTR*) ((u8*)rec + rec->value_offset);
|
||||
|
||||
dir->name_len = name->file_name_length;
|
||||
dir->name = malloc (sizeof (ntfschar) * dir->name_len);
|
||||
memcpy (dir->name, name->file_name, sizeof (ntfschar) * dir->name_len);
|
||||
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_dir_add
|
||||
*/
|
||||
void ntfs_dir_add (struct ntfs_dir *parent, struct ntfs_dir *child)
|
||||
{
|
||||
if (!parent || !child)
|
||||
return;
|
||||
|
||||
parent->child_count++;
|
||||
//printf ("child count = %d\n", parent->child_count);
|
||||
parent->children = realloc (parent->children, parent->child_count * sizeof (struct ntfs_dir*));
|
||||
child->parent = parent;
|
||||
|
||||
parent->children[parent->child_count-1] = child;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_dir_find2
|
||||
*/
|
||||
struct ntfs_dir * ntfs_dir_find2 (struct ntfs_dir *dir, ntfschar *name, int name_len)
|
||||
{
|
||||
int i;
|
||||
struct ntfs_dir *child = NULL;
|
||||
struct ntfs_dt *dt = NULL;
|
||||
int dt_num = 0;
|
||||
INDEX_ENTRY *ie;
|
||||
MFT_REF mft_num;
|
||||
|
||||
if (!dir || !name)
|
||||
return NULL;
|
||||
|
||||
if (!dir->index) { // XXX when will this happen?
|
||||
printf ("ntfs_dir_find2 - directory has no index\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dir->child_count; i++) {
|
||||
if (0 == ntfs_names_collate (name, name_len,
|
||||
dir->children[i]->name,
|
||||
dir->children[i]->name_len,
|
||||
2, IGNORE_CASE,
|
||||
dir->vol->upcase,
|
||||
dir->vol->upcase_len))
|
||||
return dir->children[i];
|
||||
}
|
||||
|
||||
dt = ntfs_dt_find2 (dir->index, name, name_len, &dt_num);
|
||||
if (!dt) {
|
||||
printf ("can't find name in dir\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ie = dt->children[dt_num];
|
||||
|
||||
mft_num = ie->indexed_file;
|
||||
|
||||
child = ntfs_dir_create (dir->vol, mft_num);
|
||||
if (!child)
|
||||
return NULL;
|
||||
|
||||
child->index = ntfs_dt_create (child, NULL, -1);
|
||||
|
||||
ntfs_dir_add (dir, child);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
|
|
226
libntfs/index.c
226
libntfs/index.c
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2004-2005 Anton Altaparmakov
|
||||
* Copyright (c) 2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -642,3 +643,228 @@ err_out:
|
|||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "index.h"
|
||||
#include "rich.h"
|
||||
|
||||
/**
|
||||
* ntfs_ie_free
|
||||
*/
|
||||
void ntfs_ie_free (INDEX_ENTRY *ie)
|
||||
{
|
||||
free (ie);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ie_create
|
||||
*/
|
||||
INDEX_ENTRY * ntfs_ie_create (void)
|
||||
{
|
||||
int length;
|
||||
INDEX_ENTRY *ie;
|
||||
|
||||
length = 16;
|
||||
ie = calloc (1, length);
|
||||
if (!ie)
|
||||
return NULL;
|
||||
|
||||
ie->indexed_file = 0;
|
||||
ie->length = length;
|
||||
ie->key_length = 0;
|
||||
ie->flags = INDEX_ENTRY_END;
|
||||
ie->reserved = 0;
|
||||
return ie;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ie_get_vcn
|
||||
*/
|
||||
VCN ntfs_ie_get_vcn (INDEX_ENTRY *ie)
|
||||
{
|
||||
if (!ie)
|
||||
return -1;
|
||||
if (!(ie->flags & INDEX_ENTRY_NODE))
|
||||
return -1;
|
||||
|
||||
return *((VCN*) ((u8*) ie + ie->length - 8));
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ie_copy
|
||||
*/
|
||||
INDEX_ENTRY * ntfs_ie_copy (INDEX_ENTRY *ie)
|
||||
{
|
||||
INDEX_ENTRY *copy = NULL;
|
||||
|
||||
if (!ie)
|
||||
return NULL;
|
||||
|
||||
copy = malloc (ie->length);
|
||||
if (!copy)
|
||||
return NULL;
|
||||
memcpy (copy, ie, ie->length);
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ie_set_vcn
|
||||
*/
|
||||
INDEX_ENTRY * ntfs_ie_set_vcn (INDEX_ENTRY *ie, VCN vcn)
|
||||
{
|
||||
if (!ie)
|
||||
return 0;
|
||||
|
||||
if (!(ie->flags & INDEX_ENTRY_NODE)) {
|
||||
ie->length += 8;
|
||||
ie = realloc (ie, ie->length);
|
||||
if (!ie)
|
||||
return NULL;
|
||||
|
||||
ie->flags |= INDEX_ENTRY_NODE;
|
||||
}
|
||||
|
||||
*((VCN*) ((u8*) ie + ie->length - 8)) = vcn;
|
||||
return ie;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ie_remove_vcn
|
||||
*/
|
||||
INDEX_ENTRY * ntfs_ie_remove_vcn (INDEX_ENTRY *ie)
|
||||
{
|
||||
if (!ie)
|
||||
return NULL;
|
||||
if (!(ie->flags & INDEX_ENTRY_NODE))
|
||||
return ie;
|
||||
|
||||
ie->length -= 8;
|
||||
ie->flags &= ~INDEX_ENTRY_NODE;
|
||||
ie = realloc (ie, ie->length);
|
||||
return ie;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ie_set_name
|
||||
*/
|
||||
INDEX_ENTRY * ntfs_ie_set_name (INDEX_ENTRY *ie, ntfschar *name, int namelen, FILE_NAME_TYPE_FLAGS nametype)
|
||||
{
|
||||
FILE_NAME_ATTR *file;
|
||||
int need;
|
||||
BOOL wipe = FALSE;
|
||||
VCN vcn = 0;
|
||||
|
||||
if (!ie || !name)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* INDEX_ENTRY
|
||||
* MFT_REF indexed_file;
|
||||
* u16 length;
|
||||
* u16 key_length;
|
||||
* INDEX_ENTRY_FLAGS flags;
|
||||
* u16 reserved;
|
||||
*
|
||||
* FILENAME
|
||||
* MFT_REF parent_directory;
|
||||
* s64 creation_time;
|
||||
* s64 last_data_change_time;
|
||||
* s64 last_mft_change_time;
|
||||
* s64 last_access_time;
|
||||
* s64 allocated_size;
|
||||
* s64 data_size;
|
||||
* FILE_ATTR_FLAGS file_attributes;
|
||||
* u32 reserved;
|
||||
* u8 file_name_length;
|
||||
* FILE_NAME_TYPE_FLAGS file_name_type;
|
||||
* ntfschar file_name[l];
|
||||
* u8 reserved[n]
|
||||
*
|
||||
* VCN vcn;
|
||||
*/
|
||||
|
||||
//printf ("key length = 0x%02X\n", ie->key_length);
|
||||
//printf ("new name length = %d\n", namelen);
|
||||
if (ie->key_length > 0) {
|
||||
file = &ie->key.file_name;
|
||||
//printf ("filename, length %d\n", file->file_name_length);
|
||||
need = ATTR_SIZE (namelen * sizeof (ntfschar) + 2) -
|
||||
ATTR_SIZE (file->file_name_length * sizeof (ntfschar) + 2);
|
||||
} else {
|
||||
//printf ("no filename\n");
|
||||
need = ATTR_SIZE (sizeof (FILE_NAME_ATTR) + (namelen * sizeof (ntfschar)));
|
||||
wipe = TRUE;
|
||||
}
|
||||
|
||||
//printf ("need 0x%02X bytes\n", need);
|
||||
|
||||
if (need != 0) {
|
||||
if (ie->flags & INDEX_ENTRY_NODE)
|
||||
vcn = ntfs_ie_get_vcn (ie);
|
||||
|
||||
ie->length += need;
|
||||
ie->key_length += need;
|
||||
|
||||
//printf ("realloc 0x%02X\n", ie->length);
|
||||
ie = realloc (ie, ie->length);
|
||||
if (!ie)
|
||||
return NULL;
|
||||
|
||||
if (ie->flags & INDEX_ENTRY_NODE)
|
||||
ie = ntfs_ie_set_vcn (ie, vcn);
|
||||
|
||||
if (wipe)
|
||||
memset (&ie->key.file_name, 0, sizeof (FILE_NAME_ATTR));
|
||||
if (need > 0)
|
||||
memset ((u8*)ie + ie->length - need, 0, need);
|
||||
}
|
||||
|
||||
memcpy (ie->key.file_name.file_name, name, namelen * sizeof (ntfschar));
|
||||
|
||||
ie->key.file_name.file_name_length = namelen;
|
||||
ie->key.file_name.file_name_type = nametype;
|
||||
ie->flags &= ~INDEX_ENTRY_END;
|
||||
|
||||
//printf ("ie->length = 0x%02X\n", ie->length);
|
||||
//printf ("ie->key_length = 0x%02X\n", ie->key_length);
|
||||
|
||||
return ie;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_ie_remove_name
|
||||
*/
|
||||
INDEX_ENTRY * ntfs_ie_remove_name (INDEX_ENTRY *ie)
|
||||
{
|
||||
VCN vcn = 0;
|
||||
|
||||
if (!ie)
|
||||
return NULL;
|
||||
if (ie->key_length == 0)
|
||||
return ie;
|
||||
|
||||
if (ie->flags & INDEX_ENTRY_NODE)
|
||||
vcn = ntfs_ie_get_vcn (ie);
|
||||
|
||||
ie->length -= ATTR_SIZE (ie->key_length);
|
||||
ie->key_length = 0;
|
||||
ie->flags |= INDEX_ENTRY_END;
|
||||
|
||||
ie = realloc (ie, ie->length);
|
||||
if (!ie)
|
||||
return NULL;
|
||||
|
||||
if (ie->flags & INDEX_ENTRY_NODE)
|
||||
ie = ntfs_ie_set_vcn (ie, vcn);
|
||||
return ie;
|
||||
}
|
||||
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
|
|
119
libntfs/inode.c
119
libntfs/inode.c
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2002-2005 Anton Altaparmakov
|
||||
* Copyright (c) 2004-2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -1083,3 +1084,121 @@ put_err_out:
|
|||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
/**
|
||||
* ntfs_inode_close2
|
||||
*/
|
||||
int ntfs_inode_close2 (ntfs_inode *ni)
|
||||
{
|
||||
if (!ni)
|
||||
return 0;
|
||||
|
||||
//printf (BOLD YELLOW "inode close %lld (%d)\n" END, ni->mft_no, ni->ref_count);
|
||||
|
||||
ni->ref_count--;
|
||||
if (ni->ref_count > 0)
|
||||
return 0;
|
||||
|
||||
// unlink
|
||||
// ino->private_data
|
||||
|
||||
// XXX temporary until we have commit/rollback
|
||||
NInoClearDirty(ni);
|
||||
|
||||
return ntfs_inode_close (ni);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_inode_open2
|
||||
*/
|
||||
ntfs_inode * ntfs_inode_open2 (ntfs_volume *vol, const MFT_REF mref)
|
||||
{
|
||||
ntfs_inode *ino = NULL;
|
||||
struct ntfs_dir *dir;
|
||||
|
||||
if (!vol)
|
||||
return NULL;
|
||||
|
||||
switch (mref) {
|
||||
case FILE_Bitmap: ino = vol->lcnbmp_ni; break;
|
||||
case FILE_MFT: ino = vol->mft_ni; break;
|
||||
case FILE_MFTMirr: ino = vol->mftmirr_ni; break;
|
||||
case FILE_root:
|
||||
dir = vol->private_data;
|
||||
if (dir)
|
||||
ino = dir->inode;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ino) {
|
||||
//printf (BOLD YELLOW "inode reuse %lld\n" END, mref);
|
||||
ino->ref_count++;
|
||||
return ino;
|
||||
}
|
||||
|
||||
ino = ntfs_inode_open (vol, mref);
|
||||
if (!ino)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
if (mref != FILE_root)
|
||||
ntfs_inode_dir_map (ino);
|
||||
*/
|
||||
|
||||
// link
|
||||
// ino->private_data
|
||||
|
||||
ino->private_data = NULL;
|
||||
ino->ref_count = 1;
|
||||
|
||||
//printf (BOLD YELLOW "inode open %lld\n" END, mref);
|
||||
return ino;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_inode_open3
|
||||
* open a deleted inode
|
||||
*/
|
||||
ntfs_inode * ntfs_inode_open3 (ntfs_volume *vol, const MFT_REF mref)
|
||||
{
|
||||
ntfs_inode *ino = NULL;
|
||||
|
||||
if (!vol)
|
||||
return NULL;
|
||||
|
||||
ino = calloc (1, sizeof (*ino));
|
||||
if (!ino)
|
||||
return NULL;
|
||||
|
||||
ino->mrec = malloc (vol->mft_record_size);
|
||||
if (!ino->mrec) {
|
||||
free (ino);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ino->mft_no = mref;
|
||||
ino->vol = vol;
|
||||
|
||||
ino->data_size = -1;
|
||||
ino->allocated_size = -1;
|
||||
|
||||
ino->private_data = NULL;
|
||||
ino->ref_count = 1;
|
||||
|
||||
if (1 != ntfs_attr_mst_pread (vol->mft_na, MREF(mref) * vol->mft_record_size, 1, vol->mft_record_size, ino->mrec)) {
|
||||
//ntfs_inode_close2 (ino); ???
|
||||
free (ino->mrec);
|
||||
free (ino);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NInoSetDirty (ino);
|
||||
return ino;
|
||||
}
|
||||
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
|
|
338
libntfs/mft.c
338
libntfs/mft.c
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2000-2004 Anton Altaparmakov
|
||||
* Copyright (c) 2005 Yura Pakhuchiy
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -1543,3 +1544,340 @@ sync_rollback:
|
|||
errno = err;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "dir.h"
|
||||
#include "tree.h"
|
||||
#include "index.h"
|
||||
#include "rich.h"
|
||||
|
||||
/**
|
||||
* ntfs_mft_remove_attr
|
||||
*/
|
||||
int ntfs_mft_remove_attr (struct ntfs_bmp *bmp, ntfs_inode *inode, ATTR_TYPES type)
|
||||
{
|
||||
ATTR_RECORD *attr20, *attrXX;
|
||||
MFT_RECORD *mft;
|
||||
u8 *src, *dst;
|
||||
int len;
|
||||
|
||||
if (!inode)
|
||||
return 1;
|
||||
|
||||
attr20 = find_first_attribute (AT_ATTRIBUTE_LIST, inode->mrec);
|
||||
if (attr20)
|
||||
return 1;
|
||||
|
||||
printf ("remove inode %lld, attr 0x%02X\n", inode->mft_no, type);
|
||||
|
||||
attrXX = find_first_attribute (type, inode->mrec);
|
||||
if (!attrXX)
|
||||
return 1;
|
||||
|
||||
if (utils_free_non_residents3 (bmp, inode, attrXX))
|
||||
return 1;
|
||||
|
||||
// remove entry
|
||||
// inode->mrec
|
||||
|
||||
mft = inode->mrec;
|
||||
//utils_dump_mem (mft, 0, mft->bytes_in_use, DM_DEFAULTS); printf ("\n");
|
||||
|
||||
//utils_dump_mem (attrXX, 0, attrXX->length, DM_DEFAULTS); printf ("\n");
|
||||
|
||||
//printf ("mrec = %p, attr = %p, diff = %d (0x%02X)\n", mft, attrXX, (u8*)attrXX - (u8*)mft, (u8*)attrXX - (u8*)mft);
|
||||
// memmove
|
||||
|
||||
dst = (u8*) attrXX;
|
||||
src = dst + attrXX->length;
|
||||
len = (((u8*) mft + mft->bytes_in_use) - src);
|
||||
|
||||
// fix mft header
|
||||
mft->bytes_in_use -= attrXX->length;
|
||||
|
||||
#if 0
|
||||
printf ("dst = 0x%02X, src = 0x%02X, len = 0x%02X\n", (dst - (u8*)mft), (src - (u8*)mft), len);
|
||||
printf ("attr %02X, len = 0x%02X\n", attrXX->type, attrXX->length);
|
||||
printf ("bytes in use = 0x%02X\n", mft->bytes_in_use);
|
||||
printf ("\n");
|
||||
#endif
|
||||
|
||||
memmove (dst, src, len);
|
||||
//utils_dump_mem (mft, 0, mft->bytes_in_use, DM_DEFAULTS); printf ("\n");
|
||||
|
||||
NInoSetDirty(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_mft_add_attr
|
||||
*/
|
||||
ATTR_RECORD * ntfs_mft_add_attr (ntfs_inode *inode, ATTR_TYPES type, u8 *data, int data_len)
|
||||
{
|
||||
MFT_RECORD *mrec;
|
||||
ATTR_RECORD *attr;
|
||||
u8 *ptr;
|
||||
u8 *src;
|
||||
u8 *dst;
|
||||
int len;
|
||||
int attr_size;
|
||||
|
||||
if (!inode)
|
||||
return NULL;
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
attr_size = ATTR_SIZE (data_len);
|
||||
|
||||
mrec = inode->mrec;
|
||||
if (!mrec)
|
||||
return NULL;
|
||||
|
||||
if ((mrec->bytes_in_use + attr_size + 0x18) > mrec->bytes_allocated) {
|
||||
printf ("attribute is too big to fit in the record\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = (u8*) inode->mrec + mrec->attrs_offset;
|
||||
while (1) {
|
||||
attr = (ATTR_RECORD*) ptr;
|
||||
|
||||
if (type < attr->type)
|
||||
break;
|
||||
|
||||
ptr += attr->length;
|
||||
}
|
||||
|
||||
//printf ("insert before attr 0x%02X\n", attr->type);
|
||||
|
||||
len = ((u8*) mrec + mrec->bytes_in_use) - ((u8*) attr);
|
||||
src = (u8*) attr;
|
||||
dst = src + attr_size + 0x18;
|
||||
|
||||
memmove (dst, src, len);
|
||||
|
||||
src = data;
|
||||
dst = (u8*) attr + 0x18;
|
||||
len = data_len;
|
||||
|
||||
// XXX wipe slack space after attr?
|
||||
|
||||
memcpy (dst, src, len);
|
||||
|
||||
mrec->bytes_in_use += attr_size + 0x18;
|
||||
|
||||
memset (attr, 0, 0x18);
|
||||
*(u32*)((u8*) attr + 0x00) = type;
|
||||
*(u32*)((u8*) attr + 0x04) = attr_size + 0x18;
|
||||
*(u16*)((u8*) attr + 0x0E) = mrec->next_attr_instance;
|
||||
*(u32*)((u8*) attr + 0x10) = data_len;
|
||||
*(u32*)((u8*) attr + 0x14) = 0x18;
|
||||
|
||||
mrec->next_attr_instance++;
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_mft_resize_resident
|
||||
*/
|
||||
int ntfs_mft_resize_resident (ntfs_inode *inode, ATTR_TYPES type, ntfschar *name, int name_len, u8 *data, int data_len)
|
||||
{
|
||||
int mft_size;
|
||||
int mft_usage;
|
||||
int mft_free;
|
||||
int attr_orig;
|
||||
int attr_new;
|
||||
u8 *src;
|
||||
u8 *dst;
|
||||
u8 *end;
|
||||
int len;
|
||||
ntfs_attr_search_ctx *ctx = NULL;
|
||||
ATTR_RECORD *arec = NULL;
|
||||
MFT_RECORD *mrec = NULL;
|
||||
int res = -1;
|
||||
|
||||
// XXX only works when attr is in base inode
|
||||
|
||||
if ((!inode) || (!inode->mrec))
|
||||
return -1;
|
||||
if ((!data) || (data_len < 0))
|
||||
return -1;
|
||||
|
||||
mrec = inode->mrec;
|
||||
|
||||
mft_size = mrec->bytes_allocated;
|
||||
mft_usage = mrec->bytes_in_use;
|
||||
mft_free = mft_size - mft_usage;
|
||||
|
||||
//printf ("mft_size = %d\n", mft_size);
|
||||
//printf ("mft_usage = %d\n", mft_usage);
|
||||
//printf ("mft_free = %d\n", mft_free);
|
||||
//printf ("\n");
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx (NULL, mrec);
|
||||
if (!ctx)
|
||||
goto done;
|
||||
|
||||
if (ntfs_attr_lookup(type, name, name_len, CASE_SENSITIVE, 0, NULL, 0, ctx) != 0)
|
||||
goto done;
|
||||
|
||||
arec = ctx->attr;
|
||||
|
||||
if (arec->non_resident) {
|
||||
printf ("attribute isn't resident\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
attr_orig = arec->value_length;
|
||||
attr_new = data_len;
|
||||
|
||||
//printf ("attr orig = %d\n", attr_orig);
|
||||
//printf ("attr new = %d\n", attr_new);
|
||||
//printf ("\n");
|
||||
|
||||
if ((attr_new - attr_orig + mft_usage) > mft_size) {
|
||||
printf ("attribute won't fit into mft record\n");
|
||||
goto done;
|
||||
}
|
||||
|
||||
//printf ("new free space = %d\n", mft_size - (attr_new - attr_orig + mft_usage));
|
||||
|
||||
src = (u8*)arec + arec->length;
|
||||
dst = src + (attr_new - attr_orig);
|
||||
end = (u8*)mrec + mft_usage;
|
||||
len = end - src;
|
||||
|
||||
//printf ("src = %d\n", src - (u8*)mrec);
|
||||
//printf ("dst = %d\n", dst - (u8*)mrec);
|
||||
//printf ("end = %d\n", end - (u8*)mrec);
|
||||
//printf ("len = %d\n", len);
|
||||
|
||||
if (src != dst)
|
||||
memmove (dst, src, len);
|
||||
|
||||
memcpy ((u8*)arec + arec->value_offset, data, data_len);
|
||||
|
||||
mrec->bytes_in_use += (attr_new - attr_orig);
|
||||
arec->length += (attr_new - attr_orig);
|
||||
arec->value_length += (attr_new - attr_orig);
|
||||
|
||||
memset ((u8*)mrec + mrec->bytes_in_use, 0, mft_size - mrec->bytes_in_use);
|
||||
|
||||
mft_usage += (attr_new - attr_orig);
|
||||
//utils_dump_mem (mrec, 0, mft_size, DM_DEFAULTS);
|
||||
res = 0;
|
||||
done:
|
||||
ntfs_attr_put_search_ctx (ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_mft_free_space
|
||||
*/
|
||||
int ntfs_mft_free_space (struct ntfs_dir *dir)
|
||||
{
|
||||
int res = 0;
|
||||
MFT_RECORD *mft;
|
||||
|
||||
if ((!dir) || (!dir->inode))
|
||||
return -1;
|
||||
|
||||
mft = (MFT_RECORD*) dir->inode->mrec;
|
||||
|
||||
res = mft->bytes_allocated - mft->bytes_in_use;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_mft_add_index
|
||||
*/
|
||||
int ntfs_mft_add_index (struct ntfs_dir *dir)
|
||||
{
|
||||
ntfs_volume *vol;
|
||||
u8 *buffer = NULL;
|
||||
ATTR_RECORD *attr = NULL;
|
||||
struct ntfs_dt *dt = NULL;
|
||||
INDEX_ENTRY *ie = NULL;
|
||||
|
||||
if (!dir)
|
||||
return 1;
|
||||
if (dir->bitmap && dir->ialloc)
|
||||
return 0;
|
||||
if (dir->bitmap || dir->ialloc)
|
||||
return 1;
|
||||
if (dir->index_size < 512)
|
||||
return 1;
|
||||
|
||||
vol = dir->vol;
|
||||
printf ("add two attrs to " YELLOW); ntfs_name_print (dir->name, dir->name_len); printf (END "\n");
|
||||
printf ("index size = %d\n", dir->index_size);
|
||||
|
||||
buffer = malloc (dir->index_size);
|
||||
if (!buffer)
|
||||
return 1;
|
||||
|
||||
dt = ntfs_dt_create (dir, dir->index, -1);
|
||||
if (!dt)
|
||||
return 1;
|
||||
|
||||
dt->vcn = 0; // New alloc record
|
||||
|
||||
ie = ntfs_ie_copy (dir->index->children[dir->index->child_count-1]);
|
||||
ie = ntfs_ie_set_vcn (ie, dt->vcn);
|
||||
|
||||
// can't replace ie yet, there may not be room
|
||||
ntfs_ie_free (ie);
|
||||
|
||||
ntfs_dt_transfer2 (dir->index, dt, 0, dir->index->child_count - 1);
|
||||
|
||||
printf ("root has %d children\n", dir->index->child_count);
|
||||
printf ("node has %d children\n", dt->child_count);
|
||||
|
||||
ntfs_dt_free (dt);
|
||||
|
||||
// create a new dt
|
||||
// attach dt to dir
|
||||
// move entries into alloc
|
||||
// shrink root
|
||||
|
||||
// transfer keys to new node
|
||||
// hook up root & alloc dts
|
||||
|
||||
// need disk allocation before here
|
||||
|
||||
// Index Allocation
|
||||
memset (buffer, 0, 128);
|
||||
attr = ntfs_mft_add_attr (dir->inode, AT_INDEX_ALLOCATION, buffer, 0x48);
|
||||
|
||||
// Bitmap
|
||||
memset (buffer, 0, 8);
|
||||
buffer[0] = 0x01;
|
||||
//printf ("inode = %p\n", dir->inode);
|
||||
attr = ntfs_mft_add_attr (dir->inode, AT_BITMAP, buffer, 8);
|
||||
|
||||
// attach alloc and bitmap to dir
|
||||
// need to create ntfs_attr's for them
|
||||
|
||||
// one indx record
|
||||
// 8 bits of bitmap
|
||||
|
||||
if (0) ntfs_bmp_find_space (NULL, 0, 0);
|
||||
|
||||
//printf ("m1 = %lld\n", vol->mft_zone_start);
|
||||
//printf ("m2 = %lld\n", vol->mft_zone_end);
|
||||
//printf ("m3 = %lld\n", vol->mft_zone_pos);
|
||||
//printf ("z1 = %lld\n", vol->data1_zone_pos);
|
||||
//printf ("z2 = %lld\n", vol->data2_zone_pos);
|
||||
|
||||
free (buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* rich.c - Temporary junk file. Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program/include file is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program (in the main directory of the Linux-NTFS
|
||||
* distribution in the file COPYING); if not, write to the Free Software
|
||||
* Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "rich.h"
|
||||
#include "layout.h"
|
||||
|
||||
/**
|
||||
* find_attribute - Find an attribute of the given type
|
||||
* @type: An attribute type, e.g. AT_FILE_NAME
|
||||
* @ctx: A search context, created using ntfs_get_attr_search_ctx
|
||||
*
|
||||
* Using the search context to keep track, find the first/next occurrence of a
|
||||
* given attribute type.
|
||||
*
|
||||
* N.B. This will return a pointer into @mft. As long as the search context
|
||||
* has been created without an inode, it won't overflow the buffer.
|
||||
*
|
||||
* Return: Pointer Success, an attribute was found
|
||||
* NULL Error, no matching attributes were found
|
||||
*/
|
||||
ATTR_RECORD * find_attribute (const ATTR_TYPES type, ntfs_attr_search_ctx *ctx)
|
||||
{
|
||||
if (!ctx) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (ntfs_attr_lookup(type, NULL, 0, 0, 0, NULL, 0, ctx) != 0) {
|
||||
Dprintf ("find_attribute didn't find an attribute of type: 0x%02x.\n", type);
|
||||
return NULL; /* None / no more of that type */
|
||||
}
|
||||
|
||||
Dprintf ("find_attribute found an attribute of type: 0x%02x.\n", type);
|
||||
return ctx->attr;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_attribute - Find the first attribute of a given type
|
||||
* @type: An attribute type, e.g. AT_FILE_NAME
|
||||
* @mft: A buffer containing a raw MFT record
|
||||
*
|
||||
* Search through a raw MFT record for an attribute of a given type.
|
||||
* The return value is a pointer into the MFT record that was supplied.
|
||||
*
|
||||
* N.B. This will return a pointer into @mft. The pointer won't stray outside
|
||||
* the buffer, since we created the search context without an inode.
|
||||
*
|
||||
* Return: Pointer Success, an attribute was found
|
||||
* NULL Error, no matching attributes were found
|
||||
*/
|
||||
ATTR_RECORD * find_first_attribute (const ATTR_TYPES type, MFT_RECORD *mft)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
ATTR_RECORD *rec;
|
||||
|
||||
if (!mft) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx (NULL, mft);
|
||||
if (!ctx) {
|
||||
//XXX Eprintf ("Couldn't create a search context.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rec = find_attribute (type, ctx);
|
||||
ntfs_attr_put_search_ctx (ctx);
|
||||
if (rec)
|
||||
Dprintf ("find_first_attribute: found attr of type 0x%02x.\n", type);
|
||||
else
|
||||
Dprintf ("find_first_attribute: didn't find attr of type 0x%02x.\n", type);
|
||||
return rec;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_name_print
|
||||
*/
|
||||
void ntfs_name_print (ntfschar *name, int name_len)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
|
||||
if (name_len) {
|
||||
ntfs_ucstombs (name, name_len, &buffer, 0);
|
||||
printf ("%s", buffer);
|
||||
free (buffer);
|
||||
} else {
|
||||
printf ("!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* utils_free_non_residents3
|
||||
*/
|
||||
int utils_free_non_residents3 (struct ntfs_bmp *bmp, ntfs_inode *inode, ATTR_RECORD *attr)
|
||||
{
|
||||
ntfs_attr *na;
|
||||
runlist_element *rl;
|
||||
LCN size;
|
||||
LCN count;
|
||||
|
||||
if (!bmp)
|
||||
return 1;
|
||||
if (!inode)
|
||||
return 1;
|
||||
if (!attr)
|
||||
return 1;
|
||||
if (!attr->non_resident)
|
||||
return 0;
|
||||
|
||||
na = ntfs_attr_open (inode, attr->type, NULL, 0);
|
||||
if (!na)
|
||||
return 1;
|
||||
|
||||
ntfs_attr_map_whole_runlist (na);
|
||||
rl = na->rl;
|
||||
size = na->allocated_size >> inode->vol->cluster_size_bits;
|
||||
for (count = 0; count < size; count += rl->length, rl++) {
|
||||
if (ntfs_bmp_set_range (bmp, rl->lcn, rl->length, 0) < 0) {
|
||||
printf (RED "set range : %lld - %lld FAILED\n" END, rl->lcn, rl->lcn+rl->length-1);
|
||||
}
|
||||
}
|
||||
ntfs_attr_close (na);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* utils_free_non_residents2
|
||||
*/
|
||||
int utils_free_non_residents2 (ntfs_inode *inode, struct ntfs_bmp *bmp)
|
||||
{
|
||||
ntfs_attr_search_ctx *ctx;
|
||||
|
||||
if (!inode)
|
||||
return -1;
|
||||
if (!bmp)
|
||||
return -1;
|
||||
|
||||
ctx = ntfs_attr_get_search_ctx (NULL, inode->mrec);
|
||||
if (!ctx) {
|
||||
printf ("can't create a search context\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (ntfs_attr_lookup(AT_UNUSED, NULL, 0, 0, 0, NULL, 0, ctx) == 0) {
|
||||
utils_free_non_residents3 (bmp, inode, ctx->attr);
|
||||
}
|
||||
|
||||
ntfs_attr_put_search_ctx (ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
File diff suppressed because it is too large
Load Diff
330
libntfs/volume.c
330
libntfs/volume.c
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright (c) 2000-2005 Anton Altaparmakov
|
||||
* Copyright (c) 2002-2005 Szabolcs Szakacsits
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This program/include file is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as published
|
||||
|
@ -1531,3 +1532,332 @@ err_out:
|
|||
ntfs_attr_put_search_ctx(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include "tree.h"
|
||||
|
||||
// XXX temp
|
||||
#define Eprintf printf
|
||||
#define Vprintf printf
|
||||
#define Qprintf printf
|
||||
|
||||
/**
|
||||
* utils_valid_device - Perform some safety checks on the device, before we start
|
||||
* @name: Full pathname of the device/file to work with
|
||||
* @force: Continue regardless of problems
|
||||
*
|
||||
* Check that the name refers to a device and that is isn't already mounted.
|
||||
* These checks can be overridden by using the force option.
|
||||
*
|
||||
* Return: 1 Success, we can continue
|
||||
* 0 Error, we cannot use this device
|
||||
*/
|
||||
int utils_valid_device (const char *name, int force)
|
||||
{
|
||||
unsigned long mnt_flags = 0;
|
||||
struct stat st;
|
||||
|
||||
#ifdef __CYGWIN32__
|
||||
/* FIXME: This doesn't work for Cygwin, so just return success for now... */
|
||||
return 1;
|
||||
#endif
|
||||
if (!name) {
|
||||
errno = EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (stat (name, &st) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
Eprintf ("The device %s doesn't exist\n", name);
|
||||
} else {
|
||||
Eprintf ("Error getting information about %s: %s\n", name, strerror (errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!S_ISBLK (st.st_mode)) {
|
||||
Vprintf ("%s is not a block device.\n", name);
|
||||
if (!force) {
|
||||
Eprintf ("Use the force option to work with files.\n");
|
||||
return 0;
|
||||
}
|
||||
Vprintf ("Forced to continue.\n");
|
||||
}
|
||||
|
||||
/* Make sure the file system is not mounted. */
|
||||
if (ntfs_check_if_mounted (name, &mnt_flags)) {
|
||||
Vprintf ("Failed to determine whether %s is mounted: %s\n", name, strerror (errno));
|
||||
if (!force) {
|
||||
Eprintf ("Use the force option to ignore this error.\n");
|
||||
return 0;
|
||||
}
|
||||
Vprintf ("Forced to continue.\n");
|
||||
} else if (mnt_flags & NTFS_MF_MOUNTED) {
|
||||
Vprintf ("The device %s, is mounted.\n", name);
|
||||
if (!force) {
|
||||
Eprintf ("Use the force option to work a mounted filesystem.\n");
|
||||
return 0;
|
||||
}
|
||||
Vprintf ("Forced to continue.\n");
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* utils_mount_volume
|
||||
*/
|
||||
ntfs_volume * utils_mount_volume (const char *device, unsigned long flags, BOOL force)
|
||||
{
|
||||
ntfs_volume *vol;
|
||||
|
||||
if (!device) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!utils_valid_device (device, force))
|
||||
return NULL;
|
||||
|
||||
vol = ntfs_mount (device, flags);
|
||||
if (!vol) {
|
||||
int err;
|
||||
|
||||
err = errno;
|
||||
Eprintf("Couldn't mount device '%s': %s\n", device,
|
||||
strerror(err));
|
||||
if (err == EOPNOTSUPP)
|
||||
Eprintf("Windows was either hibernated or did not "
|
||||
"shut down properly. Try to mount "
|
||||
"volume in windows, shut down and try "
|
||||
"again.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (vol->flags & VOLUME_IS_DIRTY) {
|
||||
Qprintf ("Volume is dirty.\n");
|
||||
if (!force) {
|
||||
Eprintf ("Run chkdsk and try again, or use the --force option.\n");
|
||||
ntfs_umount (vol, FALSE);
|
||||
return NULL;
|
||||
}
|
||||
Qprintf ("Forced to continue.\n");
|
||||
}
|
||||
|
||||
return vol;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_volume_commit
|
||||
*/
|
||||
int ntfs_volume_commit (ntfs_volume *vol)
|
||||
{
|
||||
if (!vol)
|
||||
return -1;
|
||||
|
||||
printf ("commit volume\n");
|
||||
if (ntfs_bmp_commit (vol->private_bmp1) < 0)
|
||||
return -1;
|
||||
|
||||
if (ntfs_bmp_commit (vol->private_bmp2) < 0)
|
||||
return -1;
|
||||
|
||||
if (ntfs_dir_commit (vol->private_data) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_volume_rollback
|
||||
*/
|
||||
int ntfs_volume_rollback (ntfs_volume *vol)
|
||||
{
|
||||
if (!vol)
|
||||
return -1;
|
||||
|
||||
if (ntfs_bmp_rollback (vol->private_bmp1) < 0)
|
||||
return -1;
|
||||
|
||||
if (ntfs_bmp_rollback (vol->private_bmp2) < 0)
|
||||
return -1;
|
||||
|
||||
if (ntfs_dir_rollback (vol->private_data) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_volume_umount2
|
||||
*/
|
||||
int ntfs_volume_umount2 (ntfs_volume *vol, const BOOL force)
|
||||
{
|
||||
struct ntfs_dir *dir;
|
||||
struct ntfs_bmp *bmp;
|
||||
|
||||
if (!vol)
|
||||
return 0;
|
||||
|
||||
ntfs_volume_rollback (vol);
|
||||
|
||||
dir = (struct ntfs_dir *) vol->private_data;
|
||||
vol->private_data = NULL;
|
||||
ntfs_dir_free (dir);
|
||||
|
||||
bmp = (struct ntfs_bmp *) vol->private_bmp1;
|
||||
vol->private_bmp1 = NULL;
|
||||
ntfs_bmp_free (bmp);
|
||||
|
||||
bmp = (struct ntfs_bmp *) vol->private_bmp2;
|
||||
vol->private_bmp2 = NULL;
|
||||
ntfs_bmp_free (bmp);
|
||||
|
||||
return ntfs_umount (vol, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* ntfs_volume_mount2
|
||||
*/
|
||||
ntfs_volume * ntfs_volume_mount2 (const char *device, unsigned long flags, BOOL force)
|
||||
{
|
||||
// XXX can we replace these and search by mft number? Hmm... NO.
|
||||
// unless I have a recursive search for an MFT number
|
||||
static ntfschar bmp[8] = {
|
||||
const_cpu_to_le16('$'),
|
||||
const_cpu_to_le16('B'),
|
||||
const_cpu_to_le16('i'),
|
||||
const_cpu_to_le16('t'),
|
||||
const_cpu_to_le16('m'),
|
||||
const_cpu_to_le16('a'),
|
||||
const_cpu_to_le16('p'),
|
||||
const_cpu_to_le16(0)
|
||||
};
|
||||
|
||||
static ntfschar mft[5] = {
|
||||
const_cpu_to_le16('$'),
|
||||
const_cpu_to_le16('M'),
|
||||
const_cpu_to_le16('F'),
|
||||
const_cpu_to_le16('T'),
|
||||
const_cpu_to_le16(0)
|
||||
};
|
||||
|
||||
static ntfschar mftmirr[9] = {
|
||||
const_cpu_to_le16('$'),
|
||||
const_cpu_to_le16('M'),
|
||||
const_cpu_to_le16('F'),
|
||||
const_cpu_to_le16('T'),
|
||||
const_cpu_to_le16('M'),
|
||||
const_cpu_to_le16('i'),
|
||||
const_cpu_to_le16('r'),
|
||||
const_cpu_to_le16('r'),
|
||||
const_cpu_to_le16(0)
|
||||
};
|
||||
|
||||
static ntfschar dot[2] = {
|
||||
const_cpu_to_le16('.'),
|
||||
const_cpu_to_le16(0)
|
||||
};
|
||||
|
||||
ntfs_volume *vol;
|
||||
struct ntfs_dir *dir;
|
||||
struct ntfs_dt *root;
|
||||
struct ntfs_dt *found;
|
||||
int num;
|
||||
|
||||
vol = utils_mount_volume (device, flags, force);
|
||||
if (!vol)
|
||||
return NULL;
|
||||
|
||||
vol->lcnbmp_ni ->ref_count = 1;
|
||||
vol->mft_ni ->ref_count = 1;
|
||||
vol->mftmirr_ni->ref_count = 1;
|
||||
|
||||
vol->lcnbmp_ni ->private_data = NULL;
|
||||
vol->mft_ni ->private_data = NULL;
|
||||
vol->mftmirr_ni->private_data = NULL;
|
||||
|
||||
dir = ntfs_dir_create (vol, FILE_root);
|
||||
if (!dir) {
|
||||
ntfs_volume_umount2 (vol, FALSE);
|
||||
vol = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
dir->index = ntfs_dt_create (dir, NULL, -1);
|
||||
|
||||
root = dir->index;
|
||||
|
||||
//$Bitmap
|
||||
num = -1;
|
||||
found = ntfs_dt_find2 (root, bmp, sizeof (bmp) - 1, &num);
|
||||
if ((!found) || (num < 0)) {
|
||||
printf ("can't find $Bitmap\n");
|
||||
ntfs_volume_umount2 (vol, FALSE);
|
||||
vol = NULL;
|
||||
goto done;
|
||||
}
|
||||
vol->lcnbmp_ni->ref_count++;
|
||||
vol->lcnbmp_ni->private_data = found->dir;
|
||||
found->inodes[num] = vol->lcnbmp_ni;
|
||||
|
||||
//$MFT
|
||||
num = -1;
|
||||
found = ntfs_dt_find2 (root, mft, sizeof (mft) - 1, &num);
|
||||
if ((!found) || (num < 0)) {
|
||||
printf ("can't find $MFT\n");
|
||||
ntfs_volume_umount2 (vol, FALSE);
|
||||
vol = NULL;
|
||||
goto done;
|
||||
}
|
||||
vol->mft_ni->ref_count++;
|
||||
vol->mft_ni->private_data = found->dir;
|
||||
found->inodes[num] = vol->mft_ni;
|
||||
|
||||
//$MFTMirr
|
||||
num = -1;
|
||||
found = ntfs_dt_find2 (root, mftmirr, sizeof (mftmirr) - 1, &num);
|
||||
if ((!found) || (num < 0)) {
|
||||
printf ("can't find $MFTMirr\n");
|
||||
ntfs_volume_umount2 (vol, FALSE);
|
||||
vol = NULL;
|
||||
goto done;
|
||||
}
|
||||
vol->mftmirr_ni->ref_count++;
|
||||
vol->mftmirr_ni->private_data = found->dir;
|
||||
found->inodes[num] = vol->mftmirr_ni;
|
||||
|
||||
// root directory
|
||||
num = -1;
|
||||
found = ntfs_dt_find2 (root, dot, 1, &num);
|
||||
if ((!found) || (num < 0)) {
|
||||
printf ("can't find the root directory\n");
|
||||
ntfs_volume_umount2 (vol, FALSE);
|
||||
vol = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
vol->private_data = found->dir;
|
||||
found->inodes[num] = dir->inode;
|
||||
dir->inode->private_data = found;
|
||||
dir->inode->ref_count = 2;
|
||||
|
||||
vol->private_bmp1 = ntfs_bmp_create (vol->mft_ni, AT_BITMAP, NULL, 0);
|
||||
vol->private_bmp2 = ntfs_bmp_create (vol->lcnbmp_ni, AT_DATA, NULL, 0);
|
||||
|
||||
if (!vol->private_bmp1 || !vol->private_bmp2) {
|
||||
printf ("can't find the bitmaps\n");
|
||||
ntfs_volume_umount2 (vol, FALSE);
|
||||
vol = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
return vol;
|
||||
}
|
||||
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ bin_PROGRAMS = ntfsfix ntfsinfo ntfscluster ntfsls ntfscat
|
|||
sbin_PROGRAMS = mkntfs ntfslabel ntfsundelete ntfsresize ntfsclone \
|
||||
ntfscp
|
||||
EXTRA_PROGRAMS = ntfsdump_logfile ntfswipe ntfstruncate ntfsmove \
|
||||
ntfsrm ntfsmftalloc ntfscmp
|
||||
ntfsmftalloc ntfscmp
|
||||
|
||||
man_MANS = mkntfs.8 ntfsfix.8 ntfslabel.8 ntfsinfo.8 \
|
||||
ntfsundelete.8 ntfsresize.8 ntfsprogs.8 ntfsls.8 \
|
||||
|
@ -37,6 +37,10 @@ if ENABLE_CRYPTO
|
|||
EXTRA_PROGRAMS += ntfsdecrypt
|
||||
endif
|
||||
|
||||
if ENABLE_RICH
|
||||
EXTRA_PROGRAMS += ntfsrm
|
||||
endif
|
||||
|
||||
# Set the include path.
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include/ntfs $(all_includes)
|
||||
|
||||
|
@ -93,9 +97,11 @@ endif
|
|||
|
||||
# We don't distribute these
|
||||
|
||||
if ENABLE_RICH
|
||||
ntfsrm_SOURCES = ntfsrm.c ntfsrm.h utils.c utils.h
|
||||
ntfsrm_LDADD = $(AM_LIBS)
|
||||
ntfsrm_LDFLAGS = $(AM_LFLAGS)
|
||||
endif
|
||||
|
||||
ntfstruncate_SOURCES = attrdef.c ntfstruncate.c utils.c utils.h
|
||||
ntfstruncate_LDADD = $(AM_LIBS)
|
||||
|
|
3771
ntfsprogs/ntfsrm.c
3771
ntfsprogs/ntfsrm.c
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* ntfsrm - Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2004 Richard Russon
|
||||
* Copyright (c) 2004-2005 Richard Russon
|
||||
*
|
||||
* This utility will delete files from an NTFS volume.
|
||||
*
|
||||
|
@ -26,6 +26,11 @@
|
|||
|
||||
#include "types.h"
|
||||
#include "layout.h"
|
||||
#include "volume.h"
|
||||
#include "inode.h"
|
||||
|
||||
struct ntfs_dir;
|
||||
struct ntfs_dt;
|
||||
|
||||
/**
|
||||
* struct options
|
||||
|
@ -42,54 +47,6 @@ struct options {
|
|||
int nodirty; /* Do not mark volume dirty */
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ntfs_bmp
|
||||
* a cache for either dir/$BITMAP, $MFT/$BITMAP or $Bitmap/$DATA
|
||||
*/
|
||||
struct ntfs_bmp {
|
||||
ntfs_volume *vol;
|
||||
ntfs_attr *attr;
|
||||
int count;
|
||||
u8 **data;
|
||||
VCN *data_vcn;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ntfs_dt
|
||||
*/
|
||||
struct ntfs_dt {
|
||||
struct ntfs_dir *dir;
|
||||
struct ntfs_dt *parent;
|
||||
u8 *data;
|
||||
int data_len;
|
||||
int child_count;
|
||||
INDEX_ENTRY **children;
|
||||
struct ntfs_dt **sub_nodes;
|
||||
ntfs_inode **inodes;
|
||||
VCN vcn;
|
||||
INDEX_HEADER *header;
|
||||
BOOL changed;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ntfs_dir
|
||||
*/
|
||||
struct ntfs_dir {
|
||||
ntfs_volume *vol;
|
||||
struct ntfs_dir *parent;
|
||||
ntfschar *name;
|
||||
int name_len;
|
||||
MFT_REF mft_num;
|
||||
struct ntfs_dt *index;
|
||||
struct ntfs_dir **children;
|
||||
int child_count;
|
||||
struct ntfs_bmp *bitmap;
|
||||
ntfs_inode *inode;
|
||||
ntfs_attr *iroot;
|
||||
ntfs_attr *ialloc;
|
||||
int index_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ntfs_find
|
||||
*/
|
||||
|
@ -102,18 +59,5 @@ struct ntfs_find {
|
|||
};
|
||||
|
||||
|
||||
#define RED "[31m"
|
||||
#define GREEN "[32m"
|
||||
#define YELLOW "[33m"
|
||||
#define BLUE "[34m"
|
||||
#define MAGENTA "[35m"
|
||||
#define CYAN "[36m"
|
||||
#define BOLD "[01m"
|
||||
#define END "[0m"
|
||||
|
||||
#define ROUND_UP(num,bound) (((num)+((bound)-1)) & ~((bound)-1))
|
||||
#define ROUND_DOWN(num,bound) ((num) & ~((bound)-1))
|
||||
#define ATTR_SIZE(s) ROUND_UP(s,8)
|
||||
|
||||
#endif /* _NTFSRM_H_ */
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ int utils_set_locale (void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef NTFS_RICH
|
||||
/**
|
||||
* utils_valid_device - Perform some safety checks on the device, before we start
|
||||
* @name: Full pathname of the device/file to work with
|
||||
|
@ -206,6 +207,7 @@ ntfs_volume * utils_mount_volume (const char *device, unsigned long flags, BOOL
|
|||
return vol;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* utils_parse_size - Convert a string representing a size
|
||||
* @value: String to be parsed
|
||||
|
@ -327,6 +329,7 @@ int utils_parse_range (const char *string, s64 *start, s64 *finish, BOOL scale)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#ifndef NTFS_RICH
|
||||
/**
|
||||
* find_attribute - Find an attribute of the given type
|
||||
* @type: An attribute type, e.g. AT_FILE_NAME
|
||||
|
@ -396,6 +399,7 @@ ATTR_RECORD * find_first_attribute (const ATTR_TYPES type, MFT_RECORD *mft)
|
|||
return rec;
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
* utils_inode_get_name
|
||||
*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* utils.h - Part of the Linux-NTFS project.
|
||||
*
|
||||
* Copyright (c) 2002-2003 Richard Russon
|
||||
* Copyright (c) 2002-2005 Richard Russon
|
||||
* Copyright (c) 2004 Anton Altaparmakov
|
||||
*
|
||||
* A set of shared functions for ntfs utilities
|
||||
|
@ -77,9 +77,7 @@ extern DEC_PRINTF(Eprintf)
|
|||
extern DEC_PRINTF(Vprintf)
|
||||
extern DEC_PRINTF(Qprintf)
|
||||
|
||||
int utils_valid_device (const char *name, int force);
|
||||
int utils_set_locale (void);
|
||||
ntfs_volume * utils_mount_volume (const char *device, unsigned long flags, BOOL force);
|
||||
int utils_parse_size (const char *value, s64 *size, BOOL scale);
|
||||
int utils_parse_range (const char *string, s64 *start, s64 *finish, BOOL scale);
|
||||
int utils_inode_get_name (ntfs_inode *inode, char *buffer, int bufsize);
|
||||
|
@ -89,8 +87,15 @@ int utils_mftrec_in_use (ntfs_volume *vol, MFT_REF mref);
|
|||
int utils_is_metadata (ntfs_inode *inode);
|
||||
void utils_dump_mem (void *buf, int start, int length, int ascii);
|
||||
|
||||
#ifndef _RICH_H_
|
||||
ATTR_RECORD * find_attribute (const ATTR_TYPES type, ntfs_attr_search_ctx *ctx);
|
||||
ATTR_RECORD * find_first_attribute (const ATTR_TYPES type, MFT_RECORD *mft);
|
||||
#endif
|
||||
|
||||
#if !(defined (_NTFS_VOLUME_H) && defined (NTFS_RICH))
|
||||
int utils_valid_device (const char *name, int force);
|
||||
ntfs_volume * utils_mount_volume (const char *device, unsigned long flags, BOOL force);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* defines...
|
||||
|
@ -131,4 +136,27 @@ int mft_next_record (struct mft_search_ctx *ctx);
|
|||
#define DM_BLUE (1 << 5)
|
||||
#define DM_BOLD (1 << 6)
|
||||
|
||||
#ifdef NTFS_RICH
|
||||
|
||||
#include "layout.h"
|
||||
#include "volume.h"
|
||||
#include "inode.h"
|
||||
#include "bitmap.h"
|
||||
#include "dir.h"
|
||||
|
||||
#define RED "\e[31m"
|
||||
#define GREEN "\e[32m"
|
||||
#define YELLOW "\e[33m"
|
||||
#define BLUE "\e[34m"
|
||||
#define MAGENTA "\e[35m"
|
||||
#define CYAN "\e[36m"
|
||||
#define BOLD "\e[01m"
|
||||
#define END "\e[0m"
|
||||
|
||||
#define ROUND_UP(num,bound) (((num)+((bound)-1)) & ~((bound)-1))
|
||||
#define ROUND_DOWN(num,bound) ((num) & ~((bound)-1))
|
||||
#define ATTR_SIZE(s) ROUND_UP(s,8)
|
||||
|
||||
#endif /* NTFS_RICH */
|
||||
|
||||
#endif /* _NTFS_UTILS_H_ */
|
||||
|
|
Loading…
Reference in New Issue