From ce6a516a56eab480f944436c1a0fe45924f8bb65 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Tue, 23 Nov 2010 07:01:33 +0100 Subject: [PATCH] Removed the 'rich' functionality including the ntfsrm tool. This change should be reverted once the 'rich' stuff is ported to libntfs-3g, but right now it seems like too much work. --- configure.ac | 9 - include/ntfs/Makefile.am | 1 - include/ntfs/rich.h | 40 -- libntfs/rich.c | 215 -------- ntfsprogs/Makefile.am | 10 - ntfsprogs/ntfsrm.c | 1070 -------------------------------------- ntfsprogs/ntfsrm.h | 63 --- 7 files changed, 1408 deletions(-) delete mode 100644 include/ntfs/rich.h delete mode 100644 libntfs/rich.c delete mode 100644 ntfsprogs/ntfsrm.c delete mode 100644 ntfsprogs/ntfsrm.h diff --git a/configure.ac b/configure.ac index 15b47bea..c22c05a0 100644 --- a/configure.ac +++ b/configure.ac @@ -143,15 +143,6 @@ 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 diff --git a/include/ntfs/Makefile.am b/include/ntfs/Makefile.am index 64bf2cc1..efd6c61b 100644 --- a/include/ntfs/Makefile.am +++ b/include/ntfs/Makefile.am @@ -4,7 +4,6 @@ linux_ntfsinclude_HEADERS = \ gnome-vfs-method.h \ gnome-vfs-module.h \ list.h \ - rich.h \ tree.h MAINTAINERCLEANFILES = Makefile.in diff --git a/include/ntfs/rich.h b/include/ntfs/rich.h deleted file mode 100644 index b40a7a4f..00000000 --- a/include/ntfs/rich.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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" - -#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_ */ - diff --git a/libntfs/rich.c b/libntfs/rich.c deleted file mode 100644 index 1921e9dc..00000000 --- a/libntfs/rich.c +++ /dev/null @@ -1,215 +0,0 @@ -/** - * 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 - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_ERRNO_H -#include -#endif - -#ifdef HAVE_ERRNO_H -#include -#endif - -#include "rich.h" -#include "layout.h" -#include "logging.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; - } - - ntfs_log_trace ("\n"); - if (ntfs_attr_lookup(type, NULL, 0, 0, 0, NULL, 0, ctx) != 0) { - ntfs_log_debug("find_attribute didn't find an attribute of type: 0x%02x.\n", type); - return NULL; /* None / no more of that type */ - } - - ntfs_log_debug("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; - } - - ntfs_log_trace ("\n"); - ctx = ntfs_attr_get_search_ctx(NULL, mft); - if (!ctx) { - //XXX ntfs_log_error("Couldn't create a search context.\n"); - return NULL; - } - - rec = find_attribute(type, ctx); - ntfs_attr_put_search_ctx(ctx); - if (rec) - ntfs_log_debug("find_first_attribute: found attr of type 0x%02x.\n", type); - else - ntfs_log_debug("find_first_attribute: didn't find attr of type 0x%02x.\n", type); - return rec; -} - -/** - * ntfs_name_print - Send a Unicode name to the debug log - * @name: - * @name_len: - * - * Description... - * - * Returns: - */ -void ntfs_name_print(ntfschar *name, int name_len) -{ - char *buffer = NULL; - - if (name_len) { - ntfs_ucstombs(name, name_len, &buffer, 0); - ntfs_log_debug("%s", buffer); - free(buffer); - } else { - ntfs_log_debug("!"); - } -} - -/** - * utils_free_non_residents3 - Free all the non-resident attributes of an inode - * @bmp: - * @inode: - * @attr: - * - * Description... - * - * Returns: - */ -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; - - ntfs_log_trace ("\n"); - 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) { - ntfs_log_warning("set range : %lld - %lld FAILED\n", rl->lcn, rl->lcn+rl->length-1); - } - } - ntfs_attr_close(na); - - return 0; -} - -/** - * utils_free_non_residents2 - Find all the non-resident attributes of an inode - * @inode: - * @bmp: - * - * Description... - * - * Returns: - */ -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; - - ntfs_log_trace ("\n"); - ctx = ntfs_attr_get_search_ctx(NULL, inode->mrec); - if (!ctx) { - ntfs_log_info("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 */ - diff --git a/ntfsprogs/Makefile.am b/ntfsprogs/Makefile.am index b258a6ab..4aabc058 100644 --- a/ntfsprogs/Makefile.am +++ b/ntfsprogs/Makefile.am @@ -34,10 +34,6 @@ 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) @@ -91,12 +87,6 @@ ntfscmp_LDFLAGS = $(AM_LFLAGS) # 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) ntfstruncate_LDFLAGS = $(AM_LFLAGS) diff --git a/ntfsprogs/ntfsrm.c b/ntfsprogs/ntfsrm.c deleted file mode 100644 index a651556f..00000000 --- a/ntfsprogs/ntfsrm.c +++ /dev/null @@ -1,1070 +0,0 @@ -/** - * ntfsrm - Part of the Linux-NTFS project. - * - * Copyright (c) 2004-2005 Richard Russon - * - * This utility will delete files from an NTFS volume. - * - * This program 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 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 - */ - -#include "config.h" - -#ifdef HAVE_STDIO_H -#include -#endif -#ifdef HAVE_GETOPT_H -#include -#endif -#ifdef HAVE_STDLIB_H -#include -#endif -#ifdef HAVE_STRING_H -#include -#endif -#ifdef HAVE_TIME_H -#include -#endif - -#include "ntfsrm.h" -#include "rich.h" -#include "utils.h" -#include "debug.h" -#include "dir.h" -#include "lcnalloc.h" -#include "mft.h" -#include "ntfstime.h" -#include "version.h" -#include "tree.h" -#include "index.h" -#include "inode.h" -#include "logging.h" - -static const char *EXEC_NAME = "ntfsrm"; -static struct options opts; -static const char *space_line = " "; - -/** - * version - Print version information about the program - * - * Print a copyright statement and a brief description of the program. - * - * Return: none - */ -static void version(void) -{ - ntfs_log_info("\n%s v%s (libntfs-3g) - Delete files from an NTFS volume.\n\n", - EXEC_NAME, VERSION); - ntfs_log_info("Copyright (c) 2004 Richard Russon\n"); - ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home); -} - -/** - * usage - Print a list of the parameters to the program - * - * Print a list of the parameters and options for the program. - * - * Return: none - */ -static void usage(void) -{ - ntfs_log_info("\nUsage: %s [options] device file\n" - "\n" - " -r --recursive Delete files in subdirectories\n" - " -i --interactive Ask before deleting files\n" - //" -I num --inode num Delete the file with this inode number\n" - //" -U --unlink Unlink the file, deleting all references \n" - "\n" - " -D --no-dirty Do not mark volume dirty (require chkdsk)\n" - " -n --no-action Do not write to disk\n" - " -f --force Use less caution\n" - " -h --help Print this help\n" - " -q --quiet Less output\n" - " -V --version Version information\n" - " -v --verbose More output\n\n", - EXEC_NAME); - ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home); -} - -/** - * parse_options - Read and validate the programs command line - * - * Read the command line, verify the syntax and parse the options. - * This function is very long, but quite simple. - * - * Return: 1 Success - * 0 Error, one or more problems - */ -static int parse_options(int argc, char **argv) -{ - static const char *sopt = "-Dfh?inqRrVv"; //"-Dfh?I:inqRrUVv"; - static const struct option lopt[] = { - { "force", no_argument, NULL, 'f' }, - { "help", no_argument, NULL, 'h' }, - //{ "inode", required_argument, NULL, 'I' }, - { "interactive", no_argument, NULL, 'i' }, - { "no-action", no_argument, NULL, 'n' }, - { "no-dirty", no_argument, NULL, 'D' }, - { "quiet", no_argument, NULL, 'q' }, - { "recursive", no_argument, NULL, 'r' }, - //{ "unlink", no_argument, NULL, 'U' }, - { "verbose", no_argument, NULL, 'v' }, - { "version", no_argument, NULL, 'V' }, - { NULL, 0, NULL, 0 } - }; - - int c = -1; - int err = 0; - int ver = 0; - int help = 0; - int levels = 0; - - opterr = 0; /* We'll handle the errors, thank you. */ - - while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) { - switch (c) { - case 1: /* A non-option argument */ - if (!opts.device) { - opts.device = argv[optind-1]; - } else if (!opts.file) { - opts.file = argv[optind-1]; - } else { - opts.device = NULL; - opts.file = NULL; - err++; - } - break; - case 'D': - opts.nodirty++; - break; - case 'f': - opts.force++; - break; - case 'h': - case '?': - if (strncmp (argv[optind-1], "--log-", 6) == 0) { - if (!ntfs_log_parse_option (argv[optind-1])) - err++; - break; - } - help++; - break; - case 'i': - opts.interactive++; - break; - case 'n': - opts.noaction++; - break; - case 'q': - opts.quiet++; - ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET); - break; - case 'R': - case 'r': - opts.recursive++; - break; - case 'V': - ver++; - break; - case 'v': - opts.verbose++; - ntfs_log_set_levels(NTFS_LOG_LEVEL_VERBOSE); - break; - default: - ntfs_log_error("Unknown option '%s'.\n", argv[optind-1]); - err++; - break; - } - } - - /* Make sure we're in sync with the log levels */ - levels = ntfs_log_get_levels(); - if (levels & NTFS_LOG_LEVEL_VERBOSE) - opts.verbose++; - if (!(levels & NTFS_LOG_LEVEL_QUIET)) - opts.quiet++; - - if (help || ver) { - opts.quiet = 0; - } else { - if ((opts.device == NULL) || - (opts.file == NULL)) { - if (argc > 1) - ntfs_log_error("You must specify one device and one file.\n"); - err++; - } - - if (opts.quiet && opts.verbose) { - ntfs_log_error("You may not use --quiet and --verbose at the " - "same time.\n"); - err++; - } - } - - if (ver) - version(); - if (help || err) - usage(); - - return (!err && !help && !ver); -} - - -/** - * ntfs_dir_print - */ -static void ntfs_dir_print(struct ntfs_dir *dir, int indent) -{ - int i; - if (!dir) - return; - - ntfs_log_info("%.*s%p ", indent, space_line, dir); - ntfs_name_print(dir->name, dir->name_len); - ntfs_log_info("\n"); - - for (i = 0; i < dir->child_count; i++) { - ntfs_dir_print(dir->children[i], indent + 4); - } - -} - -/** - * ntfs_dt_print - */ -static void ntfs_dt_print(struct ntfs_dt *dt, int indent) -{ - int i; - - if (!dt) - return; - - ntfs_log_info("%.*s%p (%d)\n", indent, space_line, dt, dt->child_count); - - for (i = 0; i < dt->child_count; i++) { - ntfs_dt_print(dt->sub_nodes[i], indent + 4); - } -} - - -/** - * utils_array_insert - */ -static int utils_array_insert(void *ptr, int asize, int before, int count) -{ - static int esize = sizeof(u8*); - u8 *src; - u8 *dst; - int len; - - if (!ptr) - return -1; - - ntfs_log_trace ("\n"); - src = (u8*) ptr + (before * esize); - dst = src + (count * esize); - len = (asize - before) * esize; - - // XXX what about realloc? - memmove(dst, src, len); - - len = count * esize; - - memset(src, 0, len); - - return 0; -} - -/** - * utils_array_remove - */ -static int utils_array_remove(void *ptr, int asize, int first, int count) -{ - static int esize = sizeof(u8*); - u8 *src; - u8 *dst; - int len; - - if (!ptr) - return -1; - - ntfs_log_trace ("\n"); - dst = (u8*) ptr + (first * esize); - src = dst + (count * esize); - len = (asize - first) * esize; - - memmove(dst, src, len); - - src = (u8*) ptr + ((asize - count) * esize); - len = count * esize; - - memset(src, 0, len); - // XXX don't want to memset, want to realloc - - return 0; -} - - -/** - * utils_pathname_to_inode2 - */ -static BOOL utils_pathname_to_inode2(ntfs_volume *vol, struct ntfs_dir *parent, const char *pathname, struct ntfs_find *found) -{ - int len; - char *p, *q; - ntfschar *unicode = NULL; - char *ascii = NULL; - struct ntfs_dir *dir = NULL; - struct ntfs_dir *child = NULL; - struct ntfs_dt *dt = NULL; - int dt_num; - BOOL result = FALSE; - - if (!vol || !pathname || !found) { - errno = EINVAL; - return FALSE; - } - - ntfs_log_trace("\n"); - memset(found, 0, sizeof(*found)); - - if (parent) { - dir = parent; - } else { - dir = (struct ntfs_dir *) vol->private_data; - if (!dir) { - ntfs_log_error("Couldn't open the inode of the root directory.\n"); - goto close; - } - } - - unicode = malloc(MAX_PATH * sizeof(ntfschar)); - ascii = strdup(pathname); // Work with a r/w copy - if (!unicode || !ascii) { - ntfs_log_error("Out of memory.\n"); - goto close; - } - - p = ascii; - while (p && *p && *p == PATH_SEP) // Remove leading /'s - p++; - while (p && *p) { - q = strchr(p, PATH_SEP); // Find the end of the first token - if (q != NULL) { - *q = '\0'; - q++; - } - - len = ntfs_mbstoucs(p, &unicode, MAX_PATH); - if (len < 0) { - ntfs_log_error("Couldn't convert name to Unicode: %s.\n", p); - goto close; - } - - //ntfs_log_info("looking for %s in dir %lld\n", p, MREF(dir->mft_num)); - //ntfs_log_info("dir: index = %p, children = %p, inode = %p, iroot = %p, ialloc = %p, count = %d\n", dir->index, dir->children, dir->inode, dir->iroot, dir->ialloc, dir->child_count); - //if (dir->parent) - if (q) { - ntfs_log_trace("q\n"); - child = ntfs_dir_find2(dir, unicode, len); - if (!child) { - ntfs_log_info("can't find %s in %s\n", p, pathname); - goto close; - } - } else { - ntfs_log_trace("!q dir->index = %p, %d\n", dir->index, dir->index->data_len); - //ntfs_log_info("file: %s\n", p); - - dt = ntfs_dt_find2(dir->index, unicode, len, &dt_num); - if (!dt) { - ntfs_log_info("can't find %s in %s (2)\n", p, pathname); - goto close; - } - ntfs_log_debug("dt = %p, data_len = %d, parent = %p\n", dt, dt->data_len, dt->parent); - - //ntfs_log_info("dt's flags = 0x%08x\n", dt->children[dt_num]->key.file_name.file_attributes); - if (dt->children[dt_num]->key.file_name.file_attributes == FILE_ATTR_I30_INDEX_PRESENT) { - //ntfs_log_info("DIR\n"); - child = ntfs_dir_create(dir->vol, dt->children[dt_num]->indexed_file); - //ntfs_log_info("child = %p (%lld)\n", child, MREF(dt->children[dt_num]->indexed_file)); - if (child) { - child->index = ntfs_dt_create(child, NULL, -1); - ntfs_dir_add(dir, child); - } - - } - - if (dt->inodes[dt_num] == NULL) { - dt->inodes[dt_num] = ntfs_inode_open(dir->vol, dt->children[dt_num]->indexed_file); - if (!dt->inodes[dt_num]) { - ntfs_log_info("Can't open inode %lld\n", MREF(dt->children[dt_num]->indexed_file)); - goto close; - } - dt->inodes[dt_num]->ref_count = 2; - dt->inodes[dt_num]->private_data = dt; - } - - //ntfs_log_info("dt = %p,%d\n", dt, dt_num); - break; - } - - dir = child; - child = NULL; - p = q; - while (p && *p && *p == PATH_SEP) - p++; - } - - found->dir = dir; - found->dt = dt; - found->dt_index = dt_num; - found->inode = dt->inodes[dt_num]; - found->mref = found->inode->mft_no; - result = TRUE; - //ntfs_log_info("dir %p, dt %p, num %d, ino %p, %lld\n", dir, dt, dt_num, dt->inodes[dt_num], MREF(found->inode->mft_no)); -close: - free(ascii); // from strdup - free(unicode); - return result; -} - - -/** - * ntfs_mft_find_free_entry - */ -static s64 ntfs_mft_find_free_entry(ntfs_volume *vol) -{ - MFT_REF i; - u64 recs; - - if (!vol) - return -1; - - ntfs_log_trace ("\n"); - recs = vol->mft_na->initialized_size >> vol->mft_record_size_bits; - //ntfs_log_info("mft contains %lld records\n", recs); - for (i = 24; i < recs; i++) { - if (utils_mftrec_in_use(vol, i) == 0) - return i; - } - return -1; -} - -/** - * ntfs_mft_set_inuse6 - */ -static int ntfs_mft_set_inuse6(ntfs_inode *inode, struct ntfs_bmp *bmp, BOOL inuse) -{ - MFT_RECORD *rec; - - if (!inode) - return -1; - - ntfs_log_trace("\n"); - if (ntfs_bmp_set_range(bmp, (VCN) MREF(inode->mft_no), 1, inuse) < 0) - return -1; - - rec = (MFT_RECORD*) inode->mrec; - - // XXX extent inodes? - - if (inuse) - rec->flags |= MFT_RECORD_IN_USE; - else - rec->flags &= ~MFT_RECORD_IN_USE; - - // XXX inc sequence number - - NInoSetDirty(inode); - - ntfs_log_info("Modified: inode %lld MFT_RECORD header\n", inode->mft_no); - return 0; -} - - -/** - * ntfs_file_remove - */ -static int ntfs_file_remove(ntfs_volume *vol, struct ntfs_dt *del, int del_num) -{ - struct ntfs_dir *find_dir = NULL; - struct ntfs_dt *top = NULL; - struct ntfs_dt *suc = NULL; - struct ntfs_dt *old = NULL; - struct ntfs_dt *par = NULL; - struct ntfs_dt *ded = NULL; - ntfschar *uname; - int name_len; - int suc_num = 0; - int par_num = -1; - INDEX_ENTRY *del_ie = NULL; - INDEX_ENTRY *suc_ie = NULL; - INDEX_ENTRY *par_ie = NULL; - INDEX_ENTRY *add_ie = NULL; - int res; - VCN vcn; - FILE_NAME_ATTR *file = NULL; - //int i; - - if (!vol || !del) { - return 1; - } - - ntfs_log_trace ("\n"); - find_dir = del->dir; - - uname = del->children[del_num]->key.file_name.file_name; - name_len = del->children[del_num]->key.file_name.file_name_length; - - top = del->dir->index; - //ntfs_dt_find_all(top); - //ntfs_dt_print(top, 0); - - del_ie = del->children[del_num]; - //utils_dump_mem(del_ie, 0, del_ie->length, DM_DEFAULTS); - //ntfs_log_info("\n"); - - /* - * If the key is not in a leaf node, then replace it with its successor. - * Continue the delete as if the successor had been deleted. - */ - - /* - for (i = 0; i < top->child_count; i++) { - par_ie = top->children[i]; - file = &par_ie->key.file_name; ntfs_log_info("\ttop node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie)); - } - */ - - if (del->header->flags & INDEX_NODE) { - ntfs_log_info("Replace key with its successor:\n"); - - vcn = ntfs_ie_get_vcn(del_ie); - //ntfs_log_info("vcn = %lld\n", vcn); - - suc = ntfs_dt_find4(find_dir->index, uname, name_len, &suc_num); - //ntfs_log_info("succ = %p, index = %d\n", suc, suc_num); - //ntfs_log_info("\n"); - - suc_ie = ntfs_ie_copy(suc->children[suc_num]); - //utils_dump_mem(suc_ie, 0, suc_ie->length, DM_BLUE|DM_GREEN|DM_INDENT); - //ntfs_log_info("\n"); - - suc_ie = ntfs_ie_set_vcn(suc_ie, vcn); - //utils_dump_mem(suc_ie, 0, suc_ie->length, DM_BLUE|DM_GREEN|DM_INDENT); - //ntfs_log_info("\n"); - - file = &del_ie->key.file_name; ntfs_log_info("\trep name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - file = &suc_ie->key.file_name; ntfs_log_info("\tsuc name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - - //utils_dump_mem(del->data, 0, del->data_len, DM_BLUE|DM_GREEN|DM_INDENT); - if (ntfs_dt_isroot(del)) - res = ntfs_dt_root_replace(del, del_num, del_ie, suc_ie); - else - res = ntfs_dt_alloc_replace(del, del_num, del_ie, suc_ie); - //ntfs_log_info("\n"); - //utils_dump_mem(del->data, 0, del->data_len, DM_BLUE|DM_GREEN|DM_INDENT); - - ntfs_ie_free(suc_ie); - - if (res == FALSE) - goto done; - - del = suc; // Continue delete with the successor - del_num = suc_num; - del_ie = suc->children[suc_num]; - } - - //ntfs_dt_print(top, 0); - - /* - * Now we have the simpler case of deleting from a leaf node. - * If this step creates an empty node, we have more to do. - */ - - ntfs_log_info("\n"); - ntfs_log_info("Delete key:\n"); - - file = &del->children[del_num]->key.file_name; ntfs_log_info("\tdel name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - - //utils_dump_mem(del->data, 0, del->header->index_length+24, DM_BLUE|DM_GREEN|DM_INDENT); - // XXX if del->child_count == 2, we could skip this step - // no, if we combine with another node, we'll have to remember - if (ntfs_dt_isroot(del)) - ntfs_dt_root_remove(del, del_num); - else - ntfs_dt_alloc_remove(del, del_num); - //ntfs_log_info("\n"); - //utils_dump_mem(del->data, 0, del->header->index_length+24, DM_BLUE|DM_GREEN|DM_INDENT); - - if (del->child_count > 1) // XXX ntfs_dt_empty (dt), ntfs_dt_full (dt, new) - goto commit; - - /* - * Ascend the tree until we find a node that is not empty. Take the - * ancestor key and unhook it. This will free up some space in the - * index allocation. Finally add the ancestor to the node of its - * successor. - */ - - // find the key nearest the root which has no descendants - ntfs_log_info("\n"); - ntfs_log_info("Find childless parent:\n"); -#if 0 - for (par = del->parent, old = par; par; old = par, par = par->parent) { - if (par->child_count > 1) - break; - par_num = ntfs_dt_find_parent(par); - } -#endif - - ntfs_log_info("del = %p, parent = %p\n", del, del->parent); - par = del->parent; - par_num = ntfs_dt_find_parent(del); - - //utils_dump_mem(par->data, 0, par->data_len, DM_BLUE|DM_GREEN|DM_INDENT); - - ntfs_log_info("par = %p, par->parent = %p, num = %d\n", par, par->parent, par_num); - par_num = 0; // TEMP - - if (par) { - file = &par->children[par_num]->key.file_name; - ntfs_log_info("\tpar name: "); - ntfs_name_print(file->file_name, file->file_name_length); - ntfs_log_info("\n"); - } - - if (par == NULL) { - // unhook everything - goto freedts; - } - - //ntfs_dt_print(top, 0); - ntfs_log_info("\n"); - - //utils_dump_mem(par->data, 0, par->data_len, DM_BLUE|DM_GREEN|DM_INDENT); - //ntfs_log_info("\n"); - - /* - for (i = 0; i < top->child_count; i++) { - par_ie = top->children[i]; - file = &par_ie->key.file_name; ntfs_log_info("\ttop node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie)); - } - */ - - // find if parent has left siblings - if (par->children[par_num]->flags & INDEX_ENTRY_END) { - ntfs_log_info("Swap the children of the parent and its left sibling\n"); - - par_ie = par->children[par_num]; - vcn = ntfs_ie_get_vcn(par_ie); - //ntfs_log_info("\toffset = %d\n", (u8*)par_ie - par->data); ntfs_log_info("\tflags = %d\n", par_ie->flags); ntfs_log_info("\tvcn = %lld\n", vcn); ntfs_log_info("\tlength = %d\n", par_ie->length); - //utils_dump_mem(par_ie, 0, par_ie->length, DM_DEFAULTS); - //ntfs_log_info("\n"); - - //ntfs_log_info("\toffset = %d\n", (u8*)par_ie - par->data); ntfs_log_info("\tflags = %d\n", par_ie->flags); ntfs_log_info("\tvcn = %lld\n", vcn); ntfs_log_info("\tlength = %d\n", par_ie->length); - //utils_dump_mem(par_ie, 0, par_ie->length, DM_DEFAULTS); - //ntfs_log_info("\n"); - - file = &par->children[par_num] ->key.file_name; ntfs_log_info("\tpar name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - file = &par->children[par_num-1]->key.file_name; ntfs_log_info("\tsib name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - - old = par->sub_nodes[par_num]; - par->sub_nodes[par_num] = par->sub_nodes[par_num-1]; - par->sub_nodes[par_num-1] = old; - - par_ie = par->children[par_num-1]; - vcn = ntfs_ie_get_vcn(par_ie); - - par_ie = par->children[par_num]; - ntfs_ie_set_vcn(par_ie, vcn); - - par_num--; - - if (ntfs_dt_isroot(par)) - ntfs_log_info("Modified: inode %lld, $INDEX_ROOT\n", par->dir->inode->mft_no); - else - ntfs_log_info("Modified: inode %lld, $INDEX_ALLOCATION vcn %lld-%lld\n", par->dir->inode->mft_no, par->vcn, par->vcn + (par->dir->index_size>>9) - 1); - } - - //ntfs_dt_print(top, 0); - - //ntfs_log_info("\n"); - //utils_dump_mem(par->data, 0, par->data_len, DM_DEFAULTS); - - // unhook and hold onto the ded dt's - ntfs_log_info("\n"); - ntfs_log_info("Remove parent\n"); - - file = &par->children[par_num]->key.file_name; ntfs_log_info("\tpar name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - - add_ie = ntfs_ie_copy(par->children[par_num]); - add_ie = ntfs_ie_remove_vcn(add_ie); - if (!add_ie) - goto done; - - //ntfs_log_info("\n"); - //utils_dump_mem(add_ie, 0, add_ie->length, DM_BLUE|DM_GREEN|DM_INDENT); - - ded = par->sub_nodes[par_num]; - par->sub_nodes[par_num] = NULL; - //ntfs_dt_print(ded, 8); - -#if 0 - for (i = 0; i < par->child_count; i++) { - par_ie = par->children[i]; - file = &par_ie->key.file_name; ntfs_log_info("\tdel node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie)); - } -#endif - -#if 1 - //ntfs_log_info("PAR: %p,%d\n", par, par_num); - if (ntfs_dt_isroot(par)) - ntfs_dt_root_remove(par, par_num); - else - ntfs_dt_alloc_remove(par, par_num); -#endif - //ntfs_log_info("count = %d\n", par->child_count); - //utils_dump_mem(par->data, 0, par->data_len, DM_DEFAULTS); - //ntfs_log_info("0x%x\n", (u8*)par->children[0] - par->data); - -#if 0 - for (i = 0; i < par->child_count; i++) { - par_ie = par->children[i]; - file = &par_ie->key.file_name; ntfs_log_info("\tadd node, key %d: ", i); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - ntfs_log_info("\tvcn = %lld\n", ntfs_ie_get_vcn(par_ie)); - } -#endif - - //ntfs_dt_print(top, 0); - ntfs_log_info("\n"); - ntfs_log_info("Add childless parent\n"); - - file = &add_ie->key.file_name; ntfs_log_info("\tadd name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - suc = NULL; - suc_num = -1; - suc = ntfs_dt_find4(top, file->file_name, file->file_name_length, &suc_num); - //ntfs_log_info("SUC: %p, %d\n", suc, suc_num); - - if (!suc) - goto done; - - file = &suc->children[suc_num]->key.file_name; ntfs_log_info("\tsuc name: "); ntfs_name_print(file->file_name, file->file_name_length); ntfs_log_info("\n"); - - // insert key into successor - // if any new nodes are needed, reuse the preserved nodes - if (!ntfs_dt_add2(add_ie, suc, suc_num, ded)) - goto done; - - // remove any unused nodes - - // XXX mark dts, dirs and inodes dirty - // XXX add freed dts to a list for immediate reuse (attach to dir?) - // XXX any ded dts means we may need to adjust alloc - // XXX commit will free list of spare dts - // XXX reduce size of alloc - // XXX if ded, don't write it back, just update bitmap - - ntfs_log_info("empty\n"); - goto done; - -freedts: - ntfs_log_info("\twhole dir is empty\n"); - -commit: - //ntfs_log_info("commit\n"); - -done: - return 0; -} - -/** - * ntfs_file_remove2 - */ -static int ntfs_file_remove2(ntfs_volume *vol, struct ntfs_dt *dt, int dt_num) -{ - INDEX_ENTRY *ie; - ntfs_inode *ino; - struct ntfs_bmp *bmp_mft; - struct ntfs_bmp *bmp_vol; - struct ntfs_dir *dir; - - if (!vol || !dt) - return -1; - - ntfs_log_trace ("\n"); - ie = dt->children[dt_num]; - ino = dt->inodes[dt_num]; - dir = dt->dir; - - bmp_mft = vol->private_bmp1; - bmp_vol = vol->private_bmp2; - - if (1) ntfs_mft_set_inuse6(ino, bmp_mft, FALSE); - - if (1) utils_free_non_residents2(ino, bmp_vol); - - if (1) ntfs_file_remove(vol, dt, dt_num); // remove name from index - - if (1) ntfs_dir_truncate(vol, dt->dir); - - if (1) ntfs_volume_commit(vol); - - if (0) ntfs_volume_rollback(vol); - - if (0) ntfs_log_info("last mft = %lld\n", ntfs_bmp_find_last_set(bmp_mft)); - if (0) ntfs_log_info("last vol = %lld\n", ntfs_bmp_find_last_set(bmp_vol)); - - return 0; -} - -/** - * ntfs_file_add2 - */ -static int ntfs_file_add2(ntfs_volume *vol, char *filename) -{ - MFT_REF new_num; - char *ptr = NULL; - char *dirname = NULL; - struct ntfs_find find; - INDEX_ENTRY *ie = NULL; - ntfschar *uname = NULL; - int uname_len = 0; - ntfs_inode *ino = NULL; - u8 *tmp = NULL; - u8 *buffer = NULL; - s64 now = 0; - struct ntfs_dir *dir; - struct ntfs_dt *dt; - int dt_index = 0; - int data_len = 0; - ATTR_RECORD *attr; - struct ntfs_dt *suc = NULL; - int suc_num = 0; - - ntfs_log_trace("\n"); - new_num = ntfs_mft_find_free_entry(vol); - if (new_num == (MFT_REF) -1) - return 1; - - if (rindex(filename, PATH_SEP)) { - ptr = rindex(filename, PATH_SEP); - *ptr = 0; - dirname = filename; - filename = ptr + 1; - } - - ntfs_log_info("looking for %s\n", dirname); - if (utils_pathname_to_inode2(vol, NULL, dirname, &find) == FALSE) { - ntfs_log_info("!inode\n"); - return 0; - } - - dt = find.dt; - dir = find.dir; - - uname_len = ntfs_mbstoucs(filename, &uname, 0); - if (uname_len < 0) - goto close; - - ntfs_log_info("new inode %lld\n", new_num); - ino = ntfs_inode_open3(vol, new_num); - if (!ino) { - ntfs_log_info("!ino\n"); - goto close; - } - - tmp = (u8*) ino->mrec; - now = utc2ntfs(time(NULL)); - - // Wipe all the attributes - memset(tmp + ino->mrec->attrs_offset, 0, vol->mft_record_size - ino->mrec->attrs_offset); - - // Add new end marker - *(u32*) (tmp + ino->mrec->attrs_offset) = 0xFFFFFFFF; - ino->mrec->bytes_in_use = ino->mrec->attrs_offset + 8; - - // Reset headers... - ino->mrec->lsn = 0; - ino->mrec->link_count = 1; - ino->mrec->base_mft_record = 0; - ino->mrec->next_attr_instance = 0; - ino->mrec->flags = MFT_RECORD_IN_USE; - - ntfs_mft_set_inuse6(ino, vol->private_bmp1, TRUE); - - buffer = malloc(128); - if (!buffer) - goto close; - - // Standard information - memset(buffer, 0, 128); - *(u64*)(buffer + 0x00) = now; // Time - *(u64*)(buffer + 0x08) = now; // Time - *(u64*)(buffer + 0x10) = now; // Time - *(u64*)(buffer + 0x18) = now; // Time - ino->creation_time = time(NULL); - ino->last_data_change_time = time(NULL); - ino->last_mft_change_time = time(NULL); - ino->last_access_time = time(NULL); - attr = ntfs_mft_add_attr(ino, AT_STANDARD_INFORMATION, buffer, 0x48); - - // Data - memset(buffer, 0, 128); - data_len = sprintf((char*)buffer, "Contents of file: %s\n", filename); - attr = ntfs_mft_add_attr(ino, AT_DATA, buffer, data_len); - - // File name - memset(buffer, 0, 128); - *(u64*)(buffer + 0x00) = MK_MREF(find.mref, 2); // MFT Ref of parent dir - *(u64*)(buffer + 0x08) = now; // Time - *(u64*)(buffer + 0x10) = now; // Time - *(u64*)(buffer + 0x18) = now; // Time - *(u64*)(buffer + 0x20) = now; // Time - *(u64*)(buffer + 0x28) = ATTR_SIZE(data_len); // Allocated size - *(u64*)(buffer + 0x30) = data_len; // Initialised size - *(u32*)(buffer + 0x38) = 0; // Flags - *(u32*)(buffer + 0x3C) = 0; // Not relevant - *(u8* )(buffer + 0x40) = uname_len; // Filename length - *(u8* )(buffer + 0x41) = FILE_NAME_POSIX; // Filename namespace - memcpy(buffer + 0x42, uname, uname_len * sizeof(ntfschar)); - attr = ntfs_mft_add_attr(ino, AT_FILE_NAME, buffer, ATTR_SIZE(0x42 + (uname_len * sizeof(ntfschar)))); - attr->resident_flags = RESIDENT_ATTR_IS_INDEXED; - attr->name_offset = 0x18; - - ie = ntfs_ie_create(); - ie = ntfs_ie_set_name(ie, uname, uname_len, FILE_NAME_POSIX); - if (!ie) { - ntfs_log_info("!ie\n"); - goto close; - } - - // These two NEED the sequence number in the top 8 bits - ie->key.file_name.parent_directory = MK_MREF(find.mref, 2);// MFT Ref: parent dir - ie->indexed_file = MK_MREF(new_num, ino->mrec->sequence_number); - - ie->key.file_name.creation_time = now; - ie->key.file_name.last_data_change_time = now; - ie->key.file_name.last_mft_change_time = now; - ie->key.file_name.last_access_time = now; - ie->key.file_name.allocated_size = ATTR_SIZE(data_len); - ie->key.file_name.data_size = data_len; - - dir = dt->dir->children[0]; - dt = dir->index; - - ntfs_log_debug("searching for "); ntfs_name_print(uname, uname_len); ntfs_log_debug("\n"); - // find3 doesn't map new dts. don't I _want_ to map them? - suc = ntfs_dt_find3(dt, uname, uname_len, &suc_num); - - ntfs_log_debug("dt = %p, data_len = %d, parent = %p\n", dt, dt->data_len, dt->parent); - - //dt_index = ntfs_dt_root_add(dt, ie); - dt_index = ntfs_dt_add2(ie, suc, suc_num, NULL); - if (dt_index >= 0) { - dt->inodes[dt_index] = ino; - ino->ref_count++; - } - -close: - ntfs_log_debug("working inode refcount = %d\n", ino->ref_count); - free(buffer); - ntfs_inode_close2(ino); - ntfs_ie_free(ie); - free(uname); - ntfs_inode_close2(find.inode); - return 0; -} - - -/** - * main - Begin here - * - * Start from here. - * - * Return: 0 Success, the program worked - * 1 Error, something went wrong - */ -int main(int argc, char *argv[]) -{ - ntfs_volume *vol = NULL; - ntfs_inode *inode = NULL; - int flags = 0; - int result = 1; - struct ntfs_find find; - - ntfs_log_set_handler (ntfs_log_handler_stdout); - ntfs_log_set_levels (NTFS_LOG_LEVEL_TRACE); - ntfs_log_set_flags (NTFS_LOG_FLAG_COLOUR); - - ntfs_log_trace ("\n"); - if (!parse_options(argc, argv)) - goto done; - - utils_set_locale(); - -#if 0 - ntfs_log_info("sizeof(ntfs_bmp) = %d\n", sizeof(struct ntfs_bmp)); - ntfs_log_info("sizeof(ntfs_dt) = %d\n", sizeof(struct ntfs_dt)); - ntfs_log_info("sizeof(ntfs_dir) = %d\n", sizeof(struct ntfs_dir)); - ntfs_log_info("\n"); -#endif - - if (opts.noaction) - flags |= MS_RDONLY; - - //ntfs_log_set_levels (NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE); - //ntfs_log_set_levels (NTFS_LOG_LEVEL_DEBUG); - vol = ntfs_volume_mount2(opts.device, flags, opts.force); - if (!vol) { - ntfs_log_info("!vol\n"); - goto done; - } - -#if 0 - if (utils_pathname_to_inode2(vol, NULL, opts.file, &find) == FALSE) { - ntfs_log_info("!inode\n"); - goto done; - } - - inode = find.inode; -#endif - - //ntfs_log_info("inode = %lld\n", inode->mft_no); - - if (0) result = ntfs_file_remove2(vol, find.dt, find.dt_index); - if (1) result = ntfs_file_add2(vol, opts.file); - -done: - if (1) ntfs_volume_commit(vol); - if (0) ntfs_volume_rollback(vol); - if (0) ntfs_inode_close2(inode); - if (1) ntfs_volume_umount2(vol, FALSE); - - //ntfs_log_clear_levels(NTFS_LOG_LEVEL_DEBUG | NTFS_LOG_LEVEL_TRACE); - if (0) utils_pathname_to_inode2(NULL, NULL, NULL, NULL); - if (0) ntfs_ie_remove_name(NULL); - if (0) ntfs_dt_transfer2(NULL, NULL, 0, 0); - if (0) utils_array_remove(NULL, 0, 0, 0); - if (0) utils_array_insert(NULL, 0, 0, 0); - - ntfs_log_trace("result = %d\n", result); - return result; -} - diff --git a/ntfsprogs/ntfsrm.h b/ntfsprogs/ntfsrm.h deleted file mode 100644 index c37e55b8..00000000 --- a/ntfsprogs/ntfsrm.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ntfsrm - Part of the Linux-NTFS project. - * - * Copyright (c) 2004-2005 Richard Russon - * - * This utility will delete files from an NTFS volume. - * - * This program 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 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 _NTFSRM_H_ -#define _NTFSRM_H_ - -#include "types.h" -#include "layout.h" -#include "volume.h" -#include "inode.h" - -struct ntfs_dir; -struct ntfs_dt; - -/** - * struct options - */ -struct options { - char *device; /* Device/File to work with */ - char *file; /* File to delete */ - int force; /* Override common sense */ - int interactive; /* Ask before deleting files */ - int recursive; /* Delete files in subdirectories */ - int quiet; /* Less output */ - int verbose; /* Extra output */ - int noaction; /* Do not write to disk */ - int nodirty; /* Do not mark volume dirty */ -}; - -/** - * struct ntfs_find - */ -struct ntfs_find { - ntfs_inode *inode; - struct ntfs_dir *dir; - struct ntfs_dt *dt; - int dt_index; - MFT_REF mref; -}; - - -#endif /* _NTFSRM_H_ */ -