From aa7e3cc98ee930091403304484868112b0158bad Mon Sep 17 00:00:00 2001 From: antona Date: Wed, 5 Oct 2005 13:01:10 +0000 Subject: [PATCH] return volume set dirty functionality to ntfsfix on Yura's request. Anton --- ChangeLog | 1 - ntfsprogs/ntfsfix.c | 132 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 131 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4aadf2f7..ec98b1a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -55,7 +55,6 @@ xx/xx/2005 - 1.12.0-WIP set a flag, it overwrites the flags! Rename it to ntfs_volume_write_flags() and clean it up a lot. Update all callers. (Anton) - - Change ntfsfix to no longer set the volume dirty. (Anton) - Change everything to supply an ntfs_inode and NULL for mft record when calling ntfs_attr_get_search_ctx() except a very few cases which genuinely need this functionality as they work on a too low level. diff --git a/ntfsprogs/ntfsfix.c b/ntfsprogs/ntfsfix.c index c50377bb..bacafdb3 100644 --- a/ntfsprogs/ntfsfix.c +++ b/ntfsprogs/ntfsfix.c @@ -1,7 +1,7 @@ /** * NtfsFix - Part of the Linux-NTFS project. * - * Copyright (c) 2000-2003 Anton Altaparmakov. + * Copyright (c) 2000-2005 Anton Altaparmakov. * * This utility will attempt to fix a partition that has been damaged by the * current Linux-NTFS driver. It should be run after dismounting an NTFS @@ -87,6 +87,7 @@ GEN_PRINTF(Qprintf, stdout, NULL, FALSE) static const char *EXEC_NAME = "ntfsfix"; static const char *OK = "OK"; static const char *FAILED = "FAILED"; +static BOOL vol_is_dirty = FALSE; static BOOL journal_is_empty = FALSE; struct { @@ -159,6 +160,128 @@ static void parse_options(int argc, char **argv) } } +static int OLD_ntfs_volume_set_flags(ntfs_volume *vol, const u16 flags) +{ + MFT_RECORD *m = NULL; + ATTR_RECORD *a; + VOLUME_INFORMATION *c; + ntfs_attr_search_ctx *ctx; + int ret = -1; /* failure */ + + if (!vol) { + errno = EINVAL; + return -1; + } + if (ntfs_file_record_read(vol, FILE_Volume, &m, NULL)) { + Dperror("Failed to read $Volume"); + return -1; + } + /* Sanity check */ + if (!(m->flags & MFT_RECORD_IN_USE)) { + Dprintf("Error: $Volume has been deleted. Cannot " + "handle this yet. Run chkdsk to fix this.\n"); + errno = EIO; + goto err_exit; + } + /* Get a pointer to the volume information attribute. */ + ctx = ntfs_attr_get_search_ctx(NULL, m); + if (!ctx) { + Dperror("Failed to allocate attribute search context"); + goto err_exit; + } + if (ntfs_attr_lookup(AT_VOLUME_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, + 0, ctx)) { + Dputs("Error: Attribute $VOLUME_INFORMATION was not found in " + "$Volume!"); + goto err_out; + } + a = ctx->attr; + /* Sanity check. */ + if (a->non_resident) { + Dputs("Error: Attribute $VOLUME_INFORMATION must be resident " + "(and it isn't)!"); + errno = EIO; + goto err_out; + } + /* Get a pointer to the value of the attribute. */ + c = (VOLUME_INFORMATION*)(le16_to_cpu(a->value_offset) + (char*)a); + /* Sanity checks. */ + if ((char*)c + le32_to_cpu(a->value_length) > + le16_to_cpu(m->bytes_in_use) + (char*)m || + le16_to_cpu(a->value_offset) + + le32_to_cpu(a->value_length) > le32_to_cpu(a->length)) { + Dputs("Error: Attribute $VOLUME_INFORMATION in $Volume is " + "corrupt!"); + errno = EIO; + goto err_out; + } + /* Set the volume flags. */ + vol->flags = c->flags = cpu_to_le16(flags); + if (ntfs_mft_record_write(vol, FILE_Volume, m)) { + Dperror("Error writing $Volume"); + goto err_out; + } + ret = 0; /* success */ +err_out: + ntfs_attr_put_search_ctx(ctx); +err_exit: + if (m) + free(m); + return ret; +} + +static int set_dirty_flag(ntfs_volume *vol) +{ + u16 flags; + + if (vol_is_dirty == TRUE) + return 0; + + printf("Setting required flags on partition... "); + /* + * Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run + * and fix it for us. + */ + flags = vol->flags | VOLUME_IS_DIRTY; + /* If NTFS volume version >= 2.0 then set mounted on NT4 flag. */ + if (vol->major_ver >= 2) + flags |= VOLUME_MOUNTED_ON_NT4; + if (OLD_ntfs_volume_set_flags(vol, flags)) { + puts(FAILED); + fprintf(stderr, "Error setting volume flags.\n"); + return -1; + } + puts(OK); + vol_is_dirty = TRUE; + return 0; +} + +static int set_dirty_flag_mount(ntfs_volume *vol) +{ + u16 flags; + + if (vol_is_dirty == TRUE) + return 0; + + printf("Setting required flags on partition... "); + /* + * Set chkdsk flag, i.e. mark the partition dirty so chkdsk will run + * and fix it for us. + */ + flags = vol->flags | VOLUME_IS_DIRTY; + /* If NTFS volume version >= 2.0 then set mounted on NT4 flag. */ + if (vol->major_ver >= 2) + flags |= VOLUME_MOUNTED_ON_NT4; + if (ntfs_volume_write_flags(vol, flags)) { + puts(FAILED); + fprintf(stderr, "Error setting volume flags.\n"); + return -1; + } + puts(OK); + vol_is_dirty = TRUE; + return 0; +} + static int empty_journal(ntfs_volume *vol) { if (journal_is_empty == TRUE) @@ -336,6 +459,10 @@ int main(int argc, char **argv) printf("Processing of $MFT and $MFTMirr completed successfully.\n"); + /* FIXME: Will this fail? Probably... */ + if (set_dirty_flag(vol) < 0) + goto error_exit; + if (empty_journal(vol) < 0) goto error_exit; @@ -358,6 +485,9 @@ mount_ok: goto error_exit; } + if (set_dirty_flag_mount(vol) < 0) + goto error_exit; + if (empty_journal(vol) < 0) goto error_exit;