diff --git a/ntfsprogs/ntfswipe.c b/ntfsprogs/ntfswipe.c index f35decdc..f98a51e2 100644 --- a/ntfsprogs/ntfswipe.c +++ b/ntfsprogs/ntfswipe.c @@ -25,64 +25,26 @@ #include #include -#include -#include -#include #include #include #include #include #include #include +#include #include "ntfswipe.h" #include "types.h" #include "volume.h" +#include "utils.h" static const char *AUTHOR = "Richard Russon (FlatCap)"; static const char *EXEC_NAME = "ntfswipe"; static struct options opts; -/** - * Eprintf - Print error messages - */ -void Eprintf (const char *format, ...) -{ - va_list va; - va_start (va, format); - vfprintf (stderr, format, va); - va_end (va); -} - -/** - * Iprintf - Print informative messages - */ -void Iprintf (const char *format, ...) -{ - va_list va; -#ifndef DEBUG - if (opts.quiet) - return; -#endif - va_start (va, format); - vfprintf (stdout, format, va); - va_end (va); -} - -/** - * Vprintf - Print verbose messages - */ -void Vprintf (const char *format, ...) -{ - va_list va; -#ifndef DEBUG - if (!opts.verbose) - return; -#endif - va_start (va, format); - vfprintf (stdout, format, va); - va_end (va); -} +GEN_PRINTF (Eprintf, stderr, NULL, FALSE) +GEN_PRINTF (Vprintf, stdout, &opts.verbose, TRUE) +GEN_PRINTF (Iprintf, stdout, &opts.quiet, FALSE) /** * Dprintf - Print debug messages @@ -109,7 +71,7 @@ void Dprintf (const char *format, ...) * Return: 1 Success, the clusters were wiped * 0 Error, something went wrong */ -int wipe_unused (ntfs_volume *vol, int byte) +int wipe_unused (ntfs_volume *vol, int byte, enum action act) { if (!vol || (byte < 0)) return 0; @@ -129,7 +91,7 @@ int wipe_unused (ntfs_volume *vol, int byte) * Return: 1 Success, the clusters were wiped * 0 Error, something went wrong */ -int wipe_tails (ntfs_volume *vol, int byte) +int wipe_tails (ntfs_volume *vol, int byte, enum action act) { if (!vol || (byte < 0)) return 0; @@ -149,7 +111,7 @@ int wipe_tails (ntfs_volume *vol, int byte) * Return: 1 Success, the clusters were wiped * 0 Error, something went wrong */ -int wipe_mft (ntfs_volume *vol, int byte) +int wipe_mft (ntfs_volume *vol, int byte, enum action act) { if (!vol || (byte < 0)) return 0; @@ -159,7 +121,7 @@ int wipe_mft (ntfs_volume *vol, int byte) } /** - * wipe_directory - Wipe the directiry indexes + * wipe_directory - Wipe the directory indexes * @vol: An ntfs volume obtained from ntfs_mount * @byte: Overwrite with this value * @@ -169,7 +131,7 @@ int wipe_mft (ntfs_volume *vol, int byte) * Return: 1 Success, the clusters were wiped * 0 Error, something went wrong */ -int wipe_directory (ntfs_volume *vol, int byte) +int wipe_directory (ntfs_volume *vol, int byte, enum action act) { if (!vol || (byte < 0)) return 0; @@ -189,7 +151,7 @@ int wipe_directory (ntfs_volume *vol, int byte) * Return: 1 Success, the clusters were wiped * 0 Error, something went wrong */ -int wipe_logfile (ntfs_volume *vol, int byte) +int wipe_logfile (ntfs_volume *vol, int byte, enum action act) { if (!vol || (byte < 0)) return 0; @@ -209,7 +171,7 @@ int wipe_logfile (ntfs_volume *vol, int byte) * Return: 1 Success, the clusters were wiped * 0 Error, something went wrong */ -int wipe_pagefile (ntfs_volume *vol, int byte) +int wipe_pagefile (ntfs_volume *vol, int byte, enum action act) { if (!vol || (byte < 0)) return 0; @@ -218,6 +180,7 @@ int wipe_pagefile (ntfs_volume *vol, int byte) return 1; } + /** * ntfs_info - Display information about the NTFS Volume * @vol: An ntfs volume obtained from ntfs_mount @@ -230,10 +193,166 @@ int wipe_pagefile (ntfs_volume *vol, int byte) */ int ntfs_info (ntfs_volume *vol) { + u8 *buffer; + if (!vol) return 0; Iprintf ("ntfs_info\n"); + + Iprintf ("\n"); + + Iprintf ("Cluster size = %u\n", vol->cluster_size); + Iprintf ("Volume size = %lld clusters\n", vol->nr_clusters); + Iprintf ("Volume size = %lld bytes\n", vol->nr_clusters * vol->cluster_size); + Iprintf ("Volume size = %lld MiB\n", vol->nr_clusters * vol->cluster_size / (1024*1024)); /* round up? */ + + Iprintf ("\n"); + + // move back bufsize + buffer = malloc (vol->mft_record_size); + if (!buffer) + return 0; + + Iprintf ("cluster\n"); + //Iprintf ("allocated_size = %lld\n", vol->lcnbmp_na->allocated_size); + Iprintf ("data_size = %lld\n", vol->lcnbmp_na->data_size); + //Iprintf ("initialized_size = %lld\n", vol->lcnbmp_na->initialized_size); + + { + u64 offset; + u64 size = vol->lcnbmp_na->allocated_size; + int bufsize = vol->mft_record_size; + u64 use = 0; + u64 not = 0; + int i, j; + + for (offset = 0; offset < size; offset += bufsize) { + + if ((offset + bufsize) > size) + bufsize = size - offset; + + if (ntfs_attr_pread (vol->lcnbmp_na, offset, bufsize, buffer) < bufsize) { + Eprintf ("error\n"); + return 0; + } + + for (i = 0; i < bufsize; i++) { + for (j = 0; j < 8; j++) { + if ((((offset+i)*8) + j) >= vol->nr_clusters) + goto done; + if (buffer[i] & (1 << j)) { + //printf ("*"); + use++; + } else { + //printf ("."); + not++; + } + } + } + } +done: + + Iprintf ("cluster use %lld, not %lld, total %lld\n", use, not, use+not); + Iprintf ("\n"); + + } + + { + u8 *bitmap; + u64 bmpoff; + u64 bmpsize = vol->mftbmp_na->data_size; + int bmpbufsize = 512; + int i, j; + u64 use = 0, not = 0; + + bitmap = malloc (bmpbufsize); + if (!bitmap) + return 0; + + printf ("mft has %lld records\n", vol->nr_mft_records); + + //Iprintf ("allocated_size = %lld\n", vol->mftbmp_na->allocated_size); + Iprintf ("data_size = %lld\n", vol->mftbmp_na->data_size); + //Iprintf ("initialized_size = %lld\n", vol->mftbmp_na->initialized_size); + + printf ("bmpsize = %lld\n", bmpsize); + for (bmpoff = 0; bmpoff < bmpsize; bmpoff += bmpbufsize) { + if ((bmpoff + bmpbufsize) > bmpsize) + bmpbufsize = bmpsize - bmpoff; + + //printf ("bmpbufsize = %d\n", bmpbufsize); + + if (ntfs_attr_pread (vol->mftbmp_na, bmpoff, bmpbufsize, bitmap) < bmpbufsize) { + Eprintf ("error\n"); + return 0; + } + + for (i = 0; i < bmpbufsize; i++) { + for (j = 0; j < 8; j++) { + if ((((bmpoff+i)*8) + j) >= vol->nr_mft_records) + goto bmpdone; + if (bitmap[i] & (1 << j)) { + //printf ("*"); + use++; + } else { + //printf ("."); + not++; + } + } + } + } + +bmpdone: + printf ("mft\n"); + printf ("use %lld, not %lld, total %lld\n", use, not, use+not); + + free (bitmap); + } + + + /* + * wipe_unused - volume = n clusters, u unused (%age & MB) + * $Bitmap + * vol->lcnbmp_na + * + * wipe_tails - volume = n files, total tail slack space + * $MFT, $DATA + * vol->mft_na + * + * wipe_mft - volume = n mft records, u unused, s total slack space + * $MFT, $BITMAP + * vol->mftbmp_na + * + * wipe_directory - volume has d dirs, t total slack space + * $MFT, $INDEX_ROOT, $INDEX_ALLOC, $BITMAP + * + * wipe_logfile - logfile is + * $MFT, $DATA + * + * wipe_pagefile - pagefile is + * $MFT, $DATA + */ + + free (buffer); +#if 0 + ntfs_inode *inode; + ntfs_attr *attr; + + inode = ntfs_inode_open (vol, 6); /* $Bitmap */ + if (!inode) + return 0; + + attr = ntfs_attr_open (inode, AT_DATA, NULL, 0); + if (!attr) + return 0; + + ntfs_attr_pread + + ntfs_attr_close (attr); + ntfs_inode_close (inode); +#endif + return 1; } @@ -409,6 +528,8 @@ int parse_options (int argc, char *argv[]) } break; + case 'i': + opts.info++; /* and fall through */ case 'a': opts.directory++; opts.logfile++; @@ -444,9 +565,6 @@ int parse_options (int argc, char *argv[]) case 'h': help++; break; - case 'i': - opts.info++; - break; case 'l': opts.logfile++; break; @@ -493,32 +611,32 @@ int parse_options (int argc, char *argv[]) err++; } - if ((opts.quiet) && (opts.verbose)) { + if (opts.quiet && opts.verbose) { Eprintf ("You may not use --quiet and --verbose at the same time.\n"); err++; } + /* if (opts.info && (opts.unused || opts.tails || opts.mft || opts.directory)) { Eprintf ("You may not use any other options with --info.\n"); err++; } + */ if ((opts.count < 1) || (opts.count > 100)) { Eprintf ("The iteration count must be between 1 and 100.\n"); err++; } - /*if (opts.bytes && (opts.count > 0)) { - Eprintf ("You may not use both --bytes and --count.\n"); - err++; - }*/ - /* Create a default list */ if (!opts.bytes) { opts.bytes = malloc (2 * sizeof (int)); if (opts.bytes) { opts.bytes[0] = 0; opts.bytes[1] = -1; + } else { + Eprintf ("Couldn't allocate memory for byte list.\n"); + err++; } } @@ -536,64 +654,9 @@ int parse_options (int argc, char *argv[]) return (!err && !help && !ver); } -/** - * 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 valid_device (const char *name, int force) -{ - unsigned long mnt_flags = 0; - struct stat st; - - 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"); - } - - Dprintf ("Device %s, will be used\n", name); - return 1; -} - /** - * print_summary - Tell the use what we are about to do + * print_summary - Tell the user what we are about to do * * List the operations about to be performed. The output will be silenced by * the --quiet option. @@ -649,6 +712,7 @@ int main (int argc, char *argv[]) int result = 1; int flags = 0; int i, j; + enum action act = act_info; locale = setlocale (LC_ALL, ""); if (!locale) { @@ -661,9 +725,8 @@ int main (int argc, char *argv[]) if (!parse_options (argc, argv)) return 1; - if (!valid_device (opts.device, opts.force)) { + if (!valid_device (opts.device, opts.force)) goto free; - } if (!opts.info) print_summary(); @@ -686,37 +749,90 @@ int main (int argc, char *argv[]) } if (opts.info) { - ntfs_info (vol); - result = 0; - goto umount; + act = act_info; + opts.count = 1; + } else if (opts.noaction) { + act = act_test; + } else { + act = act_wipe; } /* Even if the output it quieted, you still get 5 seconds to abort. */ - if (!opts.force) { + if ((act == act_wipe) && !opts.force) { Iprintf ("\n%s will begin in 5 seconds, press CTRL-C to abort.\n", EXEC_NAME); sleep (5); } - if (!opts.bytes) { - Eprintf ("Internal error, byte list is empty\n"); - goto umount; + if (0) + { + printf ("________________________________________________________________________________\n\n"); + int i = 0; + runlist_element *rl = vol->mft_na->rl; + for (; rl->length > 0; rl++, i++) { + printf ("%4d %lld,%lld,%lld\n", i, rl->vcn, rl->lcn, rl->length); + } + printf ("%4d %lld,%lld,%lld\n", i, rl->vcn, rl->lcn, rl->length); + return 0; } + printf ("\n"); for (i = 0; i < opts.count; i++) { int byte; + s64 total = 0; + s64 wiped = 0; + for (j = 0; byte = opts.bytes[j], byte >= 0; j++) { - if (opts.unused && !wipe_unused (vol, byte)) - goto umount; - if (opts.tails && !wipe_tails (vol, byte)) - goto umount; - if (opts.mft && !wipe_mft (vol, byte)) - goto umount; - if (opts.directory && !wipe_directory (vol, byte)) - goto umount; - if (opts.logfile && !wipe_logfile (vol, byte)) - goto umount; - if (opts.pagefile && !wipe_pagefile (vol, byte)) - goto umount; + + if (opts.directory) { + wiped = wipe_directory (vol, byte, act); + if (wiped < 0) + goto umount; + else + total += wiped; + } + + if (opts.tails) { + wiped = wipe_tails (vol, byte, act); + if (wiped < 0) + goto umount; + else + total += wiped; + } + + if (opts.logfile) { + wiped = wipe_logfile (vol, byte, act); + if (wiped < 0) + goto umount; + else + total += wiped; + } + + if (opts.mft) { + wiped = wipe_mft (vol, byte, act); + if (wiped < 0) + goto umount; + else + total += wiped; + } + + if (opts.pagefile) { + wiped = wipe_pagefile (vol, byte, act); + if (wiped < 0) + goto umount; + else + total += wiped; + } + + if (opts.unused) { + wiped = wipe_unused (vol, byte, act); + if (wiped < 0) + goto umount; + else + total += wiped; + } + + if (act == act_info) + break; } }