コード例 #1
0
        private Dictionary <int, Win32Api.UsnEntry> GetUsnRecordsDictionary()
        {
            PrivilegesManager pm = new PrivilegesManager();

            pm.Grant();
            Dictionary <int, Win32Api.UsnEntry> uEntries = new Dictionary <int, Win32Api.UsnEntry>();

            using (usnJ = new NtfsUsnJournal(/*brd.SystemDrive.MountPoint*/ brd /*.Snapshot.MountPoint*/)){
                Logger.Append(Severity.DEBUG, "Reading USN journal " + journalId + " for '" + brd.SystemDrive.MountPoint
                              + "' from seq " + prevTransactionId + " to seq " + transactionId
                              + " (changed entries from " + Utilities.Utils.GetLocalDateTimeFromUnixTime(refTimeStamp).ToString()
                              + " to " + Utilities.Utils.GetLocalDateTimeFromUnixTime(brd.Snapshot.TimeStamp).ToLocalTime().ToString() + ")");
                Win32Api.USN_JOURNAL_DATA stateJd = new Win32Api.USN_JOURNAL_DATA();
                stateJd.UsnJournalID = journalId;
                stateJd.NextUsn      = prevTransactionId;
                Win32Api.USN_JOURNAL_DATA newState          = new Win32Api.USN_JOURNAL_DATA();        // unused, as we maintain our own state
                List <Win32Api.UsnEntry>  changedUsnEntries = new List <Win32Api.UsnEntry>();
                usnJ.GetUsnJournalState(ref newState);
                NtfsUsnJournal.UsnJournalReturnCode retCode = usnJ.GetUsnJournalEntries(stateJd, refTimeStamp, 0xFFFFFFFF, out changedUsnEntries, out newState);

                if (retCode != NtfsUsnJournal.UsnJournalReturnCode.USN_JOURNAL_SUCCESS)
                {
                    throw new Exception(retCode.ToString());
                }

                int entryId = 0;
                foreach (Win32Api.UsnEntry ue in changedUsnEntries)
                {
                    if (ue != null && ue.Reason > 0)
                    {
                        entryId = (int)(ue.FileReferenceNumber);

                        //if(ue.Name.StartsWith("grut"))
                        //Console.WriteLine ("|--------| USN seq="+ue.USN+", item "+entryId+" ("+ue.Name+") "+((NtfsUsnJournal.UsnReasonCode)ue.Reason).ToString());

                        if (!uEntries.ContainsKey(entryId))
                        {
                            uEntries[entryId] = ue;
                        }
                        else                          // cumulate reason flags
                                                      // ignore created+deleted (temporary or short-lived (between 2 backups) items
                        {
                            if (
                                ((Win32Api.UsnReasonCode)ue.Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_DELETE) &&
                                ((Win32Api.UsnReasonCode)uEntries[entryId].Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_CREATE)
                                )
                            {
                                Console.WriteLine("***  item " + ue.Name + " CREATED+DELETED");
                                continue;
                            }

                            // file ID reused (file delete + new create) : totally replace previous entry
                            else if (
                                ((Win32Api.UsnReasonCode)ue.Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_CREATE) &&
                                ((Win32Api.UsnReasonCode)uEntries[entryId].Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_DELETE)
                                )
                            {
                                uEntries[entryId] = ue;
                            }

                            // cumulate flags
                            else if (!((Win32Api.UsnReasonCode)uEntries[entryId].Reason).HasFlag(((Win32Api.UsnReasonCode)ue.Reason)))
                            {
                                Win32Api.UsnReasonCode newReason = ((Win32Api.UsnReasonCode)uEntries[entryId].Reason) | ((Win32Api.UsnReasonCode)ue.Reason);
                                uEntries[entryId]        = ue;
                                uEntries[entryId].Reason = (uint)newReason;
                            }
                            // only keep the last rename operation

                            /*if(((NtfsUsnJournal.UsnReasonCode)ue.Reason).HasFlag(NtfsUsnJournal.UsnReasonCode.USN_REASON_RENAME_NEW_NAME) ){
                             *      Console.WriteLine ("***  item "+ue.Name+" RENAMED (reasons="+((NtfsUsnJournal.UsnReasonCode)ue.Reason).ToString());
                             *      NtfsUsnJournal.UsnReasonCode newReason = ((NtfsUsnJournal.UsnReasonCode)entries[entryId].Reason) ;
                             *      if(!((NtfsUsnJournal.UsnReasonCode)entries[entryId].Reason).HasFlag(NtfsUsnJournal.UsnReasonCode.USN_REASON_RENAME_NEW_NAME) )
                             *              newReason |=  NtfsUsnJournal.UsnReasonCode.USN_REASON_RENAME_NEW_NAME;
                             *      entries[entryId] = ue;
                             *      entries[entryId].Reason = (uint)newReason;
                             * }*/
                        }
                    }
                }
                Logger.Append(Severity.TRIVIA, "Done reading USN journal " + journalId + " for '" + brd.SystemDrive.MountPoint);
            }            //end using
            return(uEntries);
        }
コード例 #2
0
        public IEnumerable <IFSEntry> GetNextEntry(BasePath path, string snapshottedPath)
        {
            IFileProvider itemProv = ItemProvider.GetProvider();

            try{
                if (entries == null)
                {
                    entries = GetUsnRecordsDictionary();
                }

                Logger.Append(Severity.TRIVIA, "Got " + entries.Count + " (total for whole drive)  changed entries since reference backup");
            }
            catch (Exception e) {
                Logger.Append(Severity.ERROR, "Cannot query drive USN journal : " + e.Message);
                throw(e);
            }
            // now that we got a list with only the last usn cumulated change, analyze it
            foreach (KeyValuePair <int, Win32Api.UsnEntry> entry in entries)
            {
                string ePath = "";
                Console.WriteLine(" USN entry: " + entry.ToString());
                usnJ.GetPathFromFileReference(entry.Value.FileReferenceNumber /*(ulong)entry.Key*/, out ePath);
                ePath = brd.Snapshot.MountPoint /*Path*/.TrimEnd('\\') + ePath;
                //if(ePath.ToLower().Contains("copy") ||ePath.ToLower().Contains("docs") )
                Console.WriteLine("   ///// fullpath=" + ePath);


                IFSEntry changedItem;

                /*if(((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).HasFlag(NtfsUsnJournal.UsnReasonCode.USN_REASON_FILE_CREATE))
                 *      Console.WriteLine ("***  item "+ePath+" CREATED");
                 * else */
                if ((((Win32Api.UsnReasonCode)entry.Value.Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_FILE_DELETE)))
                {
                    /*if( (((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).HasFlag ( NtfsUsnJournal.UsnReasonCode.USN_REASON_FILE_CREATE )) ){
                     *      Console.WriteLine ("***  item "+entry.Value.Name+" CREATED+DELETED");
                     *      // TODO : handle deleted + created items (ID reused), if NTFS does so
                     *      continue;
                     * }*/
                    Console.WriteLine("***DELETEF###  item " + entry.Value.Name + " DELETED");
                    changedItem    = new NTBackupFile();
                    changedItem.ID = entry.Key;

                    changedItem.Name = entry.Value.Name;
                    //changedItem.BlockMetadata.BlockMetadata.Add(new DeletedItem());
                    changedItem.ChangeStatus = DataLayoutInfos.Deleted;


                    yield return(changedItem);

                    continue;
                }
                // item not corresponding to current wanted path.
                if (ePath.IndexOf(snapshottedPath) != 0)
                {
                    continue;
                }
                try{
                    changedItem          = itemProv.GetItemByPath(ePath);
                    changedItem.ParentID = (int)entry.Value.ParentFileReferenceNumber;


                    /*else/* if( (((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).HasFlag ( NtfsUsnJournal.UsnReasonCode.USN_REASON_DATA_EXTEND ))
                    || (((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).HasFlag ( NtfsUsnJournal.UsnReasonCode.USN_REASON_DATA_OVERWRITE ))
                    || (((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).HasFlag ( NtfsUsnJournal.UsnReasonCode.USN_REASON_DATA_TRUNCATION ))
                    || (((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).HasFlag ( NtfsUsnJournal.UsnReasonCode.USN_REASON_ENCRYPTION_CHANGE ))
                    ||      )
                    ||      {
                    ||      Console.WriteLine ("***  item "+ePath+" DATA MODIFIED");
                    ||      changedItem.BlockMetadata.BlockMetadata.Add(new Mod());
                    || }*/
                    /*else */ if ((((Win32Api.UsnReasonCode)entry.Value.Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_RENAME_NEW_NAME) ||
                                   (((Win32Api.UsnReasonCode)entry.Value.Reason).HasFlag(Win32Api.UsnReasonCode.USN_REASON_RENAME_OLD_NAME))
                                   ))
                    {
                        Console.WriteLine("***RENAMED###  item " + ePath + " RENAMED ");
                        //RenamedOrMovedItem rmi = new RenamedOrMovedItem();
                        //rmi.OldName = entry.Value.OldName;
                        //changedItem.BlockMetadata.BlockMetadata.Add(rmi);

                        // check if there is data changes , additionally to rename:
                        Win32Api.UsnReasonCode newR = ((Win32Api.UsnReasonCode)entry.Value.Reason);
                        newR &= ~Win32Api.UsnReasonCode.USN_REASON_RENAME_NEW_NAME;
                        newR &= ~Win32Api.UsnReasonCode.USN_REASON_RENAME_OLD_NAME;
                        newR &= ~Win32Api.UsnReasonCode.USN_REASON_CLOSE;

                        if ((uint)newR == 0x00000000)
                        {
                            changedItem.ChangeStatus = DataLayoutInfos.RenameOnly;
                        }
                        //changedItem.BlockMetadata.BlockMetadata.Add(new UnchangedDataItem());
                    }

                    /*else if( (((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).HasFlag ( NtfsUsnJournal.UsnReasonCode.U )) )
                     *  Console.WriteLine ("***  item "+ePath+" MOVED");*/
                }
                catch (Exception e) {              //don't add item, but report it, put backup task in Warning state
                    Logger.Append(Severity.ERROR, "Could not add item '" + ePath + "', TODO : REPORT REPORT!!. " + e.Message);
                    continue;
                }
                //Console.WriteLine ("  == usn entry path="+ePath+", reason="+((NtfsUsnJournal.UsnReasonCode)entry.Value.Reason).ToString()+" ("+entry.Value.Reason+"), ID="+ (int)(entry.Value.FileReferenceNumber)+", pid="+(int)entry.Value.ParentFileReferenceNumber);
                yield return(changedItem);
            }

            //}
        }