after creating a VSS snapshot I'd like to be able to query the USN journal. Is this possible or is the USN journal not accessible from a VSS snapshot?
my goal is to be able to use the USN journal in an incremental backup between two VSS snapshots. The process for the backup would be to
- take a VSS Snapshot and backup the volume, taking note of the USN entries for each file
- ...use the filesystem, add/delete/modify files
- take a second VSS snapshot, then use the USN journal to detect anything that changed during step #2
what I'm failing with right now is the part where I'm trying to get a hold of the highest USN entry on the VSS snapshot
- create VSS Snapshot
- open the snapshot with CreateFile(\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25)
- DeviceIoControl(FSCTL_QUERY_USN_JOURNAL) - this fails with GLE:1179 "the volume change journal is not active"
I can simulate this from the commandline as follows
C:\>vssadmin list shadows
vssadmin 1.1 - Volume Shadow Copy Service administrative command-line tool
(C) Copyright 2001-2005 Microsoft Corp.
Contents of shadow copy set ID: {54fc99fb-65f2-4558-8e12-9308979327f0}
Contained 1 shadow copies at creation time: 5/10/2012 6:44:19 PM
Shadow Copy ID: {a2d2c155-9916-47d3-96fd-94fae1c2f802}
Original Volume: (T:)\\?\Volume{a420b1fa-9744-11e1-9082-889ffaf52b70}\
Shadow Copy Volume: \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25
Originating Machine: computer
Service Machine: computer
Provider: 'Microsoft Software Shadow Copy provider 1.0'
Type: Backup
Attributes: Differential
C:\>fsutil usn queryjournal \\?\Volume{a420b1fa-9744-11e1-9082-889ffaf52b70}
Usn Journal ID : 0x01cd2ebe9c795b57
First Usn : 0x0000000000000000
Next Usn : 0x000000000001b5f8
Lowest Valid Usn : 0x0000000000000000
Max Usn : 0x7fffffffffff0000
Maximum Size : 0x0000000000100000
Allocation Delta : 0x0000000000040000
C:\>fsutil usn queryjournal \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy25
Error: The volume change journal is not active.
Any ideas what I'm doing incorrectly, if this is possible?
You may want to give Ruben's answer a second thought:
The USN Journal in a snapped volume is definitely readable by reading a special file inside the snapped VSS Volume. If the Windows API won't allow you to read the USN journal of a snapped volume then this may be a viable option although I'm sure it feels like a hack.
The thing is although NTFS does not have an open specification its been figured out by more than one project amongst which is the Linux implementations of NTFS drivers. The document that Ruben posted for you was originally written to help development of this driver.
Like I mentioned, the USN Journal content sits in a special file on your NTFS volume (like many things in NTFS e.g. The NTFS master file table. Actually it is said that everything in NTFS is a file). Special files in NTFS starts with a dollar sign $ and the one jou are looking for is named $UsnJrnl which in turn resides in a special directory named $Extend. So on your C: volume that file is
or for you snapshot it would be
The info you are looking for sits in an Alternate Data Stream named the $J stream and it has entries in this format (See Ruben's referred to doc):
So you could be reading the $J stream of this special file to get the USN entry that you want. I'm wanting to tell you how to derive the USN number that you will need but I'm a bit rusty. If I figure it out again I will update this answer. But have a look at reading special files this way, its quite fun ;-). I've used this method to read the master file table (Special file $MFT) inside an unmounted VHD file in order to enumerate all the files on the volume inside the VHD.
Perhaps this may be of use: Journal-entries do not cross cluster-boundaries. Every cluster ( normally 8 sectors per cluster) starts with a new entry. If towards the end of this cluster the next entry does not fit into the remaining cluster-space, this space is filled with zero, and the next entry ist stored at the start of the next cluster ( It's a pity this is not expressed in the "size of entry"). So you need not parse this space - just jump to the next cluster ( ! do not forget to use the RUN's of the journal to obtain the next valid disk-cluster). Robert
Btw. You can use the USN (Offset of this entry in $J), the cluster-number and the position of this entry within the Cluster to check the validity of the entry.
I think that it is impossible to use the WinAPI interface to query the USN journal while the volume is not mounted.
You can try to open the file "$UsnJrnl" and manually parse the information you need.
See:
NTFS Documentation by Richard Russon and Yuval Fledel
This question was very important for the project I'm working on, so I finally got it (almost) 100% working.
Note : all of the below code snippets are in C#
Thanks to the previous answers from Hannes de Jager who pointed me to the right direction and documentations, I can now read an USN journal from a VSS snapshot or any other special device that the regular API cannot work with ; in my case, I mean VMware snapshots mounted using the VDDK (VMware SDK for VM disks).
I also reused or imported code coming from great projects :
USN journal explorer in C#, from StCroixSkipper (http://www.dreamincode.net/forums/blog/1017-stcroixskippers-blog/). Only reads USN using the official API (so no VSS here) but provides useful pinvokes and Win32 API structures as well as general information about how USN works
AlphaFS (https://github.com/alphaleonis/AlphaFS/) , which mimics large parts of the
System.IO
namespace, but allows to access special windows paths (VSS snapshots, raw devices) and provides useful extensions as well.In case anyone else is interested, I share the code I use righ now, still in a rather crude state, but working.
How does it work?
First, you must acess the required Usn journal componenents. They are at the root of the device as ADS (alternate data streams) in an hidden entry. They cannot be accessed using the standard
System.IO
namespace, that's why I previously told I used the AlphaFS project, but pinvokingCreateFile()
andReadFile()
should be enough.1/2
The entry
\$Extend\$UsnJrnl:$Max
has global information about the current state of the journal. The most important parts are the usn journal ID (that you can use to check that the journal has not been reset if you want to compare multiple VSS snapshots) and the lowest valid USN journal sequence number.USN journal structure:
2/2
The entry
\$Extend\$UsnJrnl:$J
contains the journal records. It is a sparse file so its disk usage is much lower than it size.To answer the initial question, how can one know the Max used USN sequence from a previous VSS snapshot and compare it with that of another snapshot? Well, the NextUsn value is simply equals to the size of the
$Usnjrnl:$J
entry.On your "new" vss snapshot USN journal, you can seek to the "reference" VSS snapshot max USN before starting parsing records, if you want to parse the records changed between the two snapshots.
Generally speaking, each USN journal entry as a unique ID (USN number) which is the offset inside
$J
at whch the journal entry itself is located. Each entry has a variable size, so to sequentially read then we have to calculate:Fortunately the record length is a also a field of the USN entry record. Enough said, here is the USN record class:
I tried to isolate the smallest part of code that can parse an USN journal and extract its entries, starting from the lowest valid one. Remember, a record has a variable length; also note that some records point to a next record that is empty (the first 4 bytes, which are normally the record length, are zeroed). In this case I seek 4 bytes and retry parsing, until I get the next record. This behavior also have been reported by people having written similar parsing tools in Python so I guess I'n not too wrong here.
Here are the pinvokes I use:
This is definitely not the best piece of code on earth, but I think it will provide a good starting point for anyone having to do the same thing.