// BackupProcessor constructor: /// <summary>Initializes a new <c>BackupProcessor</c> object to use the given configuration and user interface object.</summary> /// <param name="configuration">A <c>Configuration</c> object containing all the settings for this backup run.</param> /// <param name="userInterface">A <c>ConsoleOutput</c> object which can be used for output to the user.</param> public BackupProcessor(Configuration configuration, ConsoleOutput userInterface) { // Get and store the current operating system. systemType = Configuration.getSystemType(); // Each OS has a different means of creating hard links. Set the hardLinker object to whichever type of linker is appropriate. if (systemType == Configuration.SystemType.Windows) { hardLinker = new WindowsLinker(); } else if (systemType == Configuration.SystemType.Linux) { hardLinker = new LinuxLinker(); } else { throw new NotImplementedException("Unsupported operating system."); } // Get and store the limits on use of old physical copies for creating new hard links. maxHardLinksPerFile = configuration.MaxHardLinksPerFile; maxDaysBeforeNewFullFileCopy = configuration.MaxDaysBeforeNewFullFileCopy; // Get and store the source and destination info for the backup. sourcePaths = configuration.BackupSourcePaths; backupsDestinationRootPath = configuration.BackupDestinationPath; // Set up an empty list to contain any warnings generated during the backup process. backupProcessWarnings = new List <string>(); // Store the user output object. this.userInterface = userInterface; } // end BackupProcessor constructor
public DataAccess(SystemType type) { SiteConfigurationElement connectionString = AppConfiguration.Current.GetConnectionString(type); if (connectionString == null) throw new System.Exception(string.Format("No connection string found for {0}", this.SystemType)); this._Database = new Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase(connectionString.Value); //this._Database = DatabaseFactory.CreateDatabase(connectionString.Value); this._ExecutionTimeout = connectionString.ExecutionTimeout; this.SystemType = type; }
} // end tryParseAsRule() // identifySwitch(): /// <summary>Identifies which option switch, if any, the specified string corresponds to.</summary> /// <returns> /// An <c>OptionsProcessor.SwitchType</c> value corresponding to the switch indicated by the specified string /// (which may be <c>OptionsProcessor.SwitchType.NotASwitch</c> or <c>OptionsProcessor.SwitchType.UnrecognizedSwitch</c> /// if the string does not appear to be a switch at all, or does not match a valid one). /// </returns> /// <param name="argument">A <c>string</c> containing a command-line argument, to try to identify as indicating a command-line switch.</param> /// <param name="systemType">A <c>Configuration.SystemType</c> value indicating the operating system platform currently in use.</param> private static SwitchType identifySwitch(string argument, Configuration.SystemType systemType) { SwitchType type; // Will contain the switch type ascertained by this function. // On Windows, allow a forward slash (/) to mark a command-line switch, which is common on that platform. // On Linux, we won't allow that since it is indistinguishable from the start of a path string. bool allowSlashSwitch = (systemType == Configuration.SystemType.Windows); if (argument == null) { type = SwitchType.NotASwitch; // Obviously a null string isn't a valid switch at all. } else { if (allowSlashSwitch && argument.Length > 1 && argument[0] == '/') { // String starts with a forward slash, and has at least one character following the slash, and forward-slash switches are allowed, // so grab the rest of the string after the slash and try to parse it as a switch name. string switchName = argument.Substring(1); // First try parsing it as a long switch name (e.g., "MaxHardLinkAge"). // If it isn't recognized as that, try parsing it as a short switch name (e.g., "MA"). type = parseSwitchText_long(switchName); if (type == SwitchType.NotASwitch) { type = parseSwitchText_short(switchName); } } else if (argument.Length > 2 && argument.Substring(0, 2) == "--") { // String starts with "--" switch marker and has at least one character following that. // "--" indicates a long switch name (e.g., "MaxHardLinkAge"), so parse it accordingly. type = parseSwitchText_long(argument.Substring(2)); } else if (argument.Length > 1 && argument[0] == '-') { // String starts with "-" switch marker and has at least one character following that. // "-" indicates a short switch name (e.g., "MA"), so parse it accordingly. type = parseSwitchText_short(argument.Substring(1)); } else { type = SwitchType.NotASwitch; // String doesn't fit any pattern that indicates a switch. } } return(type); } // end identifySwitch()
// getRuntimeConfiguration(): /// <summary>Parses all the options specified on the command-line string.</summary> /// <returns>A <c>Configuration</c> object containing the run-time settings for this run of the application.</returns> /// <param name="args">An array of all the command-line arguments to parse.</param> /// <exception cref="ErrorManagement.OptionsException"> /// Thrown when needed parameters are missing, specified ones are invalid, or an error is encountered reading configuration info from a specified sources file. /// </exception> /// <exception cref="OutOfMemoryException">Thrown when memory runs out trying to read the specified sources file.</exception> public static Configuration getRuntimeConfiguration(string[] args) { // Variables for holding configuration setting values to be returned. int? maxDaysBeforeNewFullFileCopy = null; int? maxHardLinksPerFile = null; List <string> commandLineSourcePaths = new List <string>(); List <SourcePathInfo> sourcePaths = new List <SourcePathInfo>(); string sourcesFilePath = null, lastReadCommandLinePath = null, backupDestinationRootPath = null; // Find out what platform we are running on. This is so we can allow switches to be defined on the command line // with a forward slash ("/") on Windows. On Linux we'll require "-" or "--" versions of the switch, because // a string starting with "/" is indistinguishable from a file path. Configuration.SystemType systemType = Configuration.getSystemType(); // Go through each argument and find out what it is. for (int i = 0; i < args.Length; i++) { // Get the current argument and identify whether it is a command line switch (e.g. "-MA") or a non-switch option. string currentArgument = args[i]; SwitchType argSwitchType = identifySwitch(currentArgument, systemType); if (argSwitchType == SwitchType.UnrecognizedSwitch) { // Seems to be a switch, but isn't a valid one. throw new OptionsException($"Unrecognized switch: {currentArgument}"); } else if (argSwitchType == SwitchType.NotASwitch) { // This argument is not a switch. The only non-switch options are the source and destination paths for the backup. // The last path specified is treated as the destination, and all others as sources. // If there already was a path argument specified, the previous one was apparently a source, not the destination, // and the destination should now be set to the newest path argument. if (lastReadCommandLinePath != null) { commandLineSourcePaths.Add(lastReadCommandLinePath); } lastReadCommandLinePath = Path.GetFullPath(currentArgument); } else { // Argument type is a recognized switch. // Get the next argument, which provides the value for the option specified. i++; if (i >= args.Length || identifySwitch(args[i], systemType) != SwitchType.NotASwitch) { // There is no next argument. The switch needs a value specified, and there isn't one. Error. throw new OptionsException($"Missing option value for switch {currentArgument}"); } string optionValue = args[i]; if (argSwitchType == SwitchType.SourcesFile) { if (sourcesFilePath == null) { sourcesFilePath = optionValue; } else { throw new OptionsException($"Switch -SF / --SourcesFile specified more than once"); // Same switch appeared more than once on the command line. } } else if (argSwitchType == SwitchType.MaxDaysBeforeNewFullFileCopy) { if (maxDaysBeforeNewFullFileCopy == null) { maxDaysBeforeNewFullFileCopy = int.Parse(optionValue); } else { throw new OptionsException($"Switch -MA / --MaxHardLinkAge specified more than once"); // Same switch appeared more than once on the command line. } } else if (argSwitchType == SwitchType.MaxHardLinksPerPhysicalFile) { if (maxHardLinksPerFile == null) { maxHardLinksPerFile = int.Parse(optionValue); } else { throw new OptionsException($"Switch -ML / --MaxHhardLinksPerFile specified more than once"); // Same switch appeared more than once on the command line. } } } // end if/else if/else block on argSwitchType } // end for (int i = 0; i < args.Length; i++) // Build the list of source paths and associated rules. foreach (string sourcePathString in commandLineSourcePaths) { sourcePaths.Add(new SourcePathInfo(sourcePathString, null)); } // If a source paths file was specified, add all its source paths and rules to the list of source paths and rules. if (sourcesFilePath != null) { sourcePaths.AddRange(readSourcePathsFile(sourcesFilePath)); // Any exception while reading this file we will just allow to bubble out to the caller. } // If two sources have the same name, the second one to be backed up will clobber the first one. Don't allow this. if (sourcePaths.GroupBy(source => source.getAllItems().First().RelativePath).Any(group => (group.Count() > 1))) { throw new OptionsException("Multiple backup source items have the same name. Back up parent directory instead or back them up to separate destinations."); } // If, when processing all the arguments, we never encountered a source path or destination path, it is an error. if (sourcePaths.Count < 1) { throw new OptionsException($"No backup source path specified"); } if (lastReadCommandLinePath == null) { throw new OptionsException($"No backup destination path specified"); } else { backupDestinationRootPath = lastReadCommandLinePath + (Path.EndsInDirectorySeparator(lastReadCommandLinePath) ? "" : Path.DirectorySeparatorChar.ToString()); } // Assemble a Configuration object based on the specified options. // For optional arguments, if they are still null (and thus weren't specified), use the default values. Configuration config = new Configuration( maxHardLinksPerFile ?? DefaultMaxHardLinksPerPhysicalFile, maxDaysBeforeNewFullFileCopy ?? DefaultMaxDaysBeforeNewFullFileCopy, sourcePaths, backupDestinationRootPath); return(config); } // end getRuntimeConfiguration()