From e80befbfb5c83975bab7e65bb1519f63a63a7b5b Mon Sep 17 00:00:00 2001 From: !szaka Date: Thu, 22 Aug 2002 18:09:47 +0000 Subject: [PATCH] Merge set_ntfs_volume_flags() and code from ntfsfix as a new library function: ntfs_set_volume_flags(). Note, ntfs_set_volume_flags() is moving to volume.[ch] 2002/07/12 12:38:54-00:00 !szaka Rewrote $LogFile reset using new inode API and moved it from ntfsfix to libntfs as ntfs_reset_logfile(). ntfsresize also resets log file. 2002/07/12 07:10:44-00:00 !szaka NTFS_V* version macros and ntfs_is_version_supported() added. Modified ntfsfix and ntfsresize to use them. 2002/07/11 16:20:34-00:00 !flatcap whitespace and include guards 2002/07/08 23:27:17-00:00 !flatcap added AT_NONAME so we can search for a (un)named attribute or just iterate through all attributes 2002/07/07 19:44:57-00:00 !antona Change ntfs_read_file_record() not to abort if the inode is not in use. Adapt callers which care to check this themselves. 2002/07/03 21:56:01-00:00 !antona Updates 2002/07/02 23:47:11-00:00 !antona Global replacement of __[su]{8,16,32,64} with [su]{8,16,32,64} and layout.h define it. 2002/06/05 20:32:53-00:00 !antona Mft mirror now updated from ntfs_write_mft_record, yey! Fixup ntfstools accordingly. 2002/06/02 23:02:20-00:00 !antona More fixes and updates. 2002/04/29 01:53:55-00:00 !antona Loads of stuff. Improvements, start on attr pread and attr mst_pread. Write to follow. ntfslabel cleanup and extensions. libntfs cleanups, fixes, etc. 2002/04/27 19:49:10-00:00 !antona Update library, new APIs ntfs_attr_find_vcn(), misc fixes and cleanups, make all the utilities compile, fix bugs I noticed in ntfslabel and it now works properly. 2002/04/21 01:26:39-00:00 !antona Cleanup/streamline include file dependencies. 2002/04/20 23:09:43-00:00 !antona Port attribute lookup functions with attribute list support from ntfs tng driver. Port/reimplement extent mft record handling code as well. Rename out all dollar signs from type names and constants. Adapt all callers to new API. Note mkntfs is currently broken due to some needed work. 2002/04/20 01:53:03-00:00 !antona Rename mft code adding ntfs_ prefix. Change all return values to zero on success. Thanks to mattjf for pointing out the inconsistencies. 2002/04/19 21:09:55-00:00 !antona Finished provisional inode.c::ntfs_{open,close}_inode() functions. Also, started defining API provided by attrib.[ch], so far only done search context related stuff. 2002/04/16 15:34:32-00:00 !antona Fix the library... 2002/04/15 19:17:24-00:00 !antona Fix ntfsfix as well. This completes all changes and everything should be just as functional as before. 2002/04/14 14:15:47-00:00 !antona Cleanups and updates. 2002/03/12 22:11:02-00:00 !antona Final tidyups. 2002/03/12 22:00:44-00:00 !antona Fix a few small mistakes 2002/03/12 21:48:27-00:00 !antona Change version numbers of mkntfs and ntfsfix to match linux-ntfs release and add options to mkntfs to disable content indexing on the volume and to enable compression on the volume. 2002/01/26 02:22:05-00:00 !antona Fix two bugs (we called is_baad_record instead of is_baad_recordp...). Thanks to David Martinez Moreno for reporting the compile time warnings on ia64 which led me to find the bugs. 2001/12/06 01:14:52-00:00 !antona Added mount flags to ntfs_mount and adapted utilities to new mount syntax. 2001/11/09 18:24:32-00:00 !antona Updates to docs, layout.h and ntfsfix to support Windows XP NTFS 2001/08/02 01:44:57-00:00 !antona Add ntfsfix man page and spell fixes. Update to 1.2.1 version and update all text files to go with it and the rpm spec file. 2001/06/01 02:07:26-00:00 !antona It has been a long time since last commit. At moment have done a lot of work on mkntfs but also at the moment ntfsfix and ntfsdump_logfile and libntfs are broken. Basically only mkntfs works and that is not complete either. 2001/04/11 15:47:36-00:00 !antona Fix 2001/04/11 15:29:39-00:00 !flatcap minor build fixes 2001/04/08 03:02:55-00:00 !antona Added cvs Id header. 2001/04/02 23:02:41-00:00 !antona Fixed a braino the compiler didn't catch... 2001/04/02 02:38:39-00:00 !antona I think version reporting is now fixed. 2001/04/02 02:20:53-00:00 !antona Fixed up the automatic version numbering (I hope). 2001/04/02 02:13:57-00:00 !antona Make the ntfsfix version be equal to the Revision in CVS. 2001/04/02 02:04:37-00:00 !antona Everything compiles again! Yey! (Don't know about working though, haven't tried it... So be careful...) The definitely final find_{first_}attr() functions are in place. Currently still no support for attribute lists. The two new _RE files contain the C-fied and more or less (more less than more actually) cleaned up functions from the ntfs driver. Once they are cleaned up (find_attr() is already completed but I left it in the _RE files for future reference/educational value) and modified to suit my ideas of how they should work, which are not quite the same as the driver way, they will make it into attrib.[ch]. If anyone gives the new code a try, I would be interested in whether it worked or not... (-; 2001/03/02 15:06:37-00:00 !antona Full commit of my current dircetory. New files not yet added. 2001/02/03 04:21:49-00:00 !antona Finished first public release. This is the final commit to make sure everything is in cvs. 2001/02/02 00:16:18-00:00 !antona Changed make process to using autoconf/automake/libtool. Added necessary files for this and for the gnu standard. Inititial checkin. Probably still stuff missing. Will know soon... 2001/01/30 12:55:21-00:00 !antona Fixed the compilation issues. 2001/01/27 14:22:02-00:00 !antona Added a logfile dumper as a new utility. Almost finished the first ntfsfix release. (Still missingin CVS are attrib.c for ntfslib and the makefiles to build everything.) Fixes for nested packed structure/union typedefs as gcc doesn't automatically nest the __attribute__ ((__packed__)), even though according to the gcc info page it does. (Thanks to Yuri Per for pointing this out.) 2001/01/24 21:02:37-00:00 !antona Added ntfsfix program. (Logical change 1.5) --- ntfstools/ntfsfix.c | 317 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) diff --git a/ntfstools/ntfsfix.c b/ntfstools/ntfsfix.c index e69de29b..e852061b 100644 --- a/ntfstools/ntfsfix.c +++ b/ntfstools/ntfsfix.c @@ -0,0 +1,317 @@ +/* + * $Id$ + * + * NtfsFix - Part of the Linux-NTFS project. + * + * Copyright (c) 2000-2002 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 a NTFS + * partition that has been mounted read-write under Linux and before rebooting + * into Windows NT/2000. NtfsFix can be run even after Windows has had mounted + * the partition, but it might be too late and irreversible damage to the data + * might have been done already. + * + * Anton Altaparmakov + * + * 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 source + * in the file COPYING); if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * WARNING: This program might not work on architectures which do not allow + * unaligned access. For those, the program would need to start using + * get/put_unaligned macros (#include ), but not doing it yet, + * since NTFS really mostly applies to ia32 only, which does allow unaligned + * accesses. We might not actually have a problem though, since the structs are + * defined as being packed so that might be enough for gcc to insert the + * correct code. + * + * If anyone using a non-little endian and/or an aligned access only CPU tries + * this program please let me know whether it works or not! + * + * Anton Altaparmakov + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "attrib.h" +#include "mft.h" +#include "disk_io.h" +#include "logfile.h" + +int main(int argc, char **argv) +{ + s64 l, br; + const char *EXEC_NAME = "NtfsFix"; + const char *OK = "OK"; + const char *FAILED = "FAILED"; + unsigned char *m = NULL, *m2 = NULL; + ntfs_volume *vol; + unsigned long mnt_flags; + int i; + u16 flags; + BOOL done, force = FALSE; + + printf("\n"); + if (argc != 2 || !argv[1]) { + printf("%s v%s - Attempt to fix an NTFS partition that " + "has been damaged by the\nLinux NTFS driver. Note that " + "you should run it every time after you have used\nthe " + "Linux NTFS driver to write to an NTFS partition to " + "prevent massive data\ncorruption from happening when " + "Windows mounts the partition.\nIMPORTANT: Run this " + "only *after* unmounting the partition in Linux but " + "*before*\nrebooting into Windows NT/2000/XP or you " + "*will* suffer! - You have been warned!\n\n" + /* Generic copyright / disclaimer. */ + "Copyright (c) 2000-2002 Anton Altaparmakov.\n\n" + "%s is free software, released under the GNU " + "General Public License and you\nare welcome to " + "redistribute it under certain conditions.\n" + "%s comes with ABSOLUTELY NO WARRANTY; for details " + "read the file GNU\nGeneral Public License to be found " + "in the file COPYING in the main Linux-NTFS\n" + "distribution directory.\n\n" + /* Generic part ends here. */ + "Syntax: ntfsfix partition_or_file_name\n" + " e.g. ntfsfix /dev/hda6\n\n", EXEC_NAME, + VERSION, EXEC_NAME, EXEC_NAME); + fprintf(stderr, "Error: incorrect syntax\n"); + exit(1); + } + if (!ntfs_check_if_mounted(argv[1], &mnt_flags)) { + if ((mnt_flags & NTFS_MF_MOUNTED) && + !(mnt_flags & NTFS_MF_READONLY) && !force) { + fprintf(stderr, "Refusing to operate on read-write " + "mounted device %s.\n", argv[1]); + exit(1); + } + } else + fprintf(stderr, "Failed to determine whether %s is mounted: " + "%s\n", argv[1], strerror(errno)); + /* Attempt a full mount first. */ + printf("Mounting volume... "); + vol = ntfs_mount(argv[1], 0); + if (vol) { + puts(OK); + printf("\nProcessing of $MFT and $MFTMirr completed " + "successfully.\n\n"); + goto mount_ok; + } + puts(FAILED); + + puts("Attempting to correct errors."); + + vol = ntfs_startup_volume(argv[1], 0); + if (!vol) { + puts(FAILED); + perror("Failed to startup volume"); + fprintf(stderr, "Volume is corrupt. You should run chkdsk."); + goto error_exit; + } + + puts("Processing $MFT and $MFTMirr."); + + /* Load data from $MFT and $MFTMirr and compare the contents. */ + m = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits); + m2 = (u8*)malloc(vol->mftmirr_size << vol->mft_record_size_bits); + if (!m || !m2) { + perror("Failed to allocate memory"); + goto error_exit; + } + + printf("Reading $MFT... "); + l = ntfs_attr_mst_pread(vol->mft_na, 0, vol->mftmirr_size, + vol->mft_record_size, m); + if (l != vol->mftmirr_size) { + puts(FAILED); + if (l != -1) + errno = EIO; + perror("Failed to read $MFT"); + goto error_exit; + } + puts(OK); + + printf("Reading $MFTMirr... "); + l = ntfs_attr_mst_pread(vol->mftmirr_na, 0, vol->mftmirr_size, + vol->mft_record_size, m2); + if (l != vol->mftmirr_size) { + puts(FAILED); + if (l != -1) + errno = EIO; + perror("Failed to read $MFTMirr"); + goto error_exit; + } + puts(OK); + + /* + * FIXME: Need to actually check the $MFTMirr for being real. Otherwise + * we might corrupt the partition if someone is experimenting with + * software RAID and the $MFTMirr is not actually in the position we + * expect it to be... )-: + * FIXME: We should emit a warning it $MFTMirr is damaged and ask + * user whether to recreate it from $MFT or whether to abort. - The + * warning needs to include the danger of software RAID arrays. + * Maybe we should go as far as to detect whether we are running on a + * MD disk and if yes then bomb out right at the start of the program? + */ + + printf("Comparing $MFTMirr to $MFT... "); + done = FALSE; + for (i = 0; i < vol->mftmirr_size; ++i) { + const char *ESTR[12] = { "$MFT", "$MFTMirr", "$LogFile", + "$Volume", "$AttrDef", "root directory", "$Bitmap", + "$Boot", "$BadClus", "$Secure", "$UpCase", "$Extend" }; + const char *s; + + if (i < 12) + s = ESTR[i]; + else if (i < 16) + s = "system file"; + else + s = "mft record"; + + if (is_baad_recordp(m + i * vol->mft_record_size)) { + puts("FAILED"); + fprintf(stderr, "$MFT error: Incomplete multi sector " + "transfer detected in %s.\nCannot " + "handle this yet. )-:\n", s); + goto error_exit; + } + if (!is_mft_recordp(m + i * vol->mft_record_size)) { + puts("FAILED"); + fprintf(stderr, "$MFT error: Invalid mft record for " + "%s.\nCannot handle this yet. )-:\n", + s); + goto error_exit; + } + if (is_baad_recordp(m2 + i * vol->mft_record_size)) { + puts("FAILED"); + fprintf(stderr, "$MFTMirr error: Incomplete multi " + "sector transfer detected in %s.\n", s); + goto error_exit; + } + if (!is_mft_recordp(m2 + i * vol->mft_record_size)) { + puts("FAILED"); + fprintf(stderr, "$MFTMirr error: Invalid mft record " + "for %s.\n", s); + goto error_exit; + } + if (memcmp((u8*)m + i * vol->mft_record_size, (u8*)m2 + + i * vol->mft_record_size, + ntfs_get_mft_record_data_size((MFT_RECORD*)( + (u8*)m + i * vol->mft_record_size)))) { + if (!done) { + done = TRUE; + puts(FAILED); + printf("Correcting differences in " + "$MFTMirr... "); + } + br = ntfs_write_mft_record(vol, i, (MFT_RECORD*)(m + + i * vol->mft_record_size)); + if (br) { + puts(FAILED); + perror("Error correcting $MFTMirr"); + goto error_exit; + } + } + } + puts(OK); + + free(m); + free(m2); + m = m2 = NULL; + + printf("Processing of $MFT and $MFTMirr completed successfully.\n\n"); + if (ntfs_umount(vol, 0)) + ntfs_umount(vol, 1); + vol = ntfs_mount(argv[1], 0); + if (!vol) { + perror("Remount failed"); + goto error_exit; + } +mount_ok: + m = NULL; + + /* Check NTFS version is ok for us (in $Volume) */ + printf("NTFS volume version is %i.%i.\n\n", vol->major_ver, + vol->minor_ver); + if (ntfs_is_version_supported(vol)) { + fprintf(stderr, "Error: Unknown NTFS version.\n"); + goto error_exit; + } + + 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_set_volume_flags(vol, flags)) { + puts(FAILED); + fprintf(stderr, "Error setting volume flags.\n"); + goto error_exit; + } + puts(OK); + printf("\n"); + + printf("Going to empty the journal ($LogFile)... "); + if (ntfs_reset_logfile(vol)) { + puts(FAILED); + perror("Failed to reset $LogFile"); + goto error_exit; + } + puts(OK); + printf("\n"); + + if (vol->major_ver >= 3) { + /* FIXME: If on NTFS 3.0+, check for presence of the usn journal and + disable it (if present) as Win2k might be unhappy otherwise and Bad + Things(TM) could happen depending on what applications are actually + using it for. */ + } + + /* FIXME: Should we be marking the quota out of date, too? */ + + /* That's all for now! */ + printf("NTFS partition %s was processed successfully.\n", + vol->dev_name); + /* Set return code to 0. */ + i = 0; +final_exit: + if (m) + free(m); + if (m2) + free(m2); + if (vol && ntfs_umount(vol, 0)) + ntfs_umount(vol, 1); + return i; +error_exit: + i = 1; + goto final_exit; +} +