2 // Inclusion of standard header file
19 // Inclusion of system header file
26 // Inclusion of library header file
28 #include <boost/filesystem/convenience.hpp>
29 #include <boost/filesystem/fstream.hpp>
30 #include <boost/filesystem/operations.hpp>
31 #include <boost/filesystem/path.hpp>
32 #include <boost/format.hpp>
33 #include <boost/lexical_cast.hpp>
34 #include <islib/binary_compare.hpp>
35 #include <islib/fatal_error.hpp>
36 #include <islib/islibfunc.hpp>
37 #include <islib/normal_termination.hpp>
38 #include <islib/program.hpp>
39 #include <islib/system_error.hpp>
40 #include <islib/trim.hpp>
43 // Inclusion of configuration file
47 #endif // HAVE_CONFIG_H
52 typedef std::vector < std::string > string_vector_type;
53 typedef boost::shared_ptr < boost::filesystem::path > path_pointer_type;
54 typedef boost::shared_ptr < string_vector_type > string_vector_pointer_type;
57 // Definition of file scope static constant
59 static char const Program_Name [] = "alstede";
60 static char const Version [] = VERSION;
61 static int const Copyright_Year = 2009;
62 static char const Person_Entitiled_To_Copyright [] = "I.S.";
63 static char const Licence_Name [] = "License GPLv3+: GNU GPL version 3 or later";
64 static char const Licence_Url [] = "http://gnu.org/licenses/gpl.html";
65 static char const Writer_Name [] = "I.S.";
66 static char const Home_Environment_Variable [] = "HOME";
67 static int const Number_Of_Static_Arguments = 2;
68 static char const Delete_Option_Character = 'D';
69 static char const Hour_Option_Character = 'H';
70 static char const Minute_Option_Character = 'M';
71 static char const Second_Option_Character = 'S';
72 static char const Version_Option_Character = 'V';
73 static char const Day_Option_Character = 'd';
74 static char const Help_Option_Character = 'h';
75 static char const Lexical_Option_Character = 'l';
76 static char const Month_Option_Character = 'm';
77 static char const Recursive_Option_Character = 'r';
78 static char const Verbose_Option_Character = 'v';
79 static char const Year_Option_Character = 'y';
80 static char const Option_String [] =
82 Delete_Option_Character,
83 Hour_Option_Character,
84 Minute_Option_Character,
85 Second_Option_Character,
86 Version_Option_Character,
88 Help_Option_Character,
89 Lexical_Option_Character,
91 Month_Option_Character,
92 Recursive_Option_Character,
93 Verbose_Option_Character,
94 Year_Option_Character,
97 static char const Delete_Option_String [] = "delete";
98 static char const Hour_Option_String [] = "hour";
99 static char const Minute_Option_String [] = "minute";
100 static char const Second_Option_String [] = "second";
101 static char const Version_Option_String [] = "version";
102 static char const Day_Option_String [] = "day";
103 static char const Help_Option_String [] = "help";
104 static char const Lexical_Option_String [] = "lexical";
105 static char const Month_Option_String [] = "month";
106 static char const Recursive_Option_String [] = "recursive";
107 static char const Verbose_Option_String [] = "verbose";
108 static char const Year_Option_String [] = "year";
109 static struct option const Long_Option_Array [] =
112 Delete_Option_String,
115 Hour_Option_Character
121 Hour_Option_Character
124 Minute_Option_String,
127 Minute_Option_Character
130 Second_Option_String,
133 Second_Option_Character
136 Version_Option_String,
139 Version_Option_Character
151 Help_Option_Character
154 Lexical_Option_String,
157 Lexical_Option_Character
163 Month_Option_Character
166 Recursive_Option_String,
169 Recursive_Option_Character
172 Verbose_Option_String,
175 Verbose_Option_Character
181 Year_Option_Character
190 static char const Extension_Configuration_File_Name [] = ".alstede_extensions";
191 static char const Comment_Character = '#';
194 // Declaration of file scope static variable
196 static path_pointer_type Home_Directory_Path;
197 static path_pointer_type Extension_Configuration_File_Path;
198 static bool Delete_Mode_Flag = false;
199 static bool Year_Mode_Flag = false;
200 static bool Month_Mode_Flag = false;
201 static bool Day_Mode_Flag = false;
202 static bool Hour_Mode_Flag = false;
203 static bool Minute_Mode_Flag = false;
204 static bool Second_Mode_Flag = false;
205 static bool Lexical_Mode_Flag = false;
206 static bool Recursive_Mode_Flag = false;
207 static bool Verbose_Mode_Flag = false;
208 static std::size_t Lexical_Depth = 0;
209 static path_pointer_type Source_Directory_Path;
210 static path_pointer_type Destination_Directory_Path;
211 static string_vector_pointer_type Extension_Vector;
214 // Declaration of static function
216 static boost::filesystem::path get_extension_configuration_file_path ();
217 static void interpret_options ( int, char ** );
218 static void read_extension_configuration_file ();
219 static void process_directory ( boost::filesystem::path const & );
220 static void print_version_message ();
221 static void print_help_message ();
222 static std::size_t get_lexical_depth ( char * );
223 static void check_flags ();
224 static void check_number_of_arguments ( int, char **, int );
225 static boost::filesystem::path get_directory_path ( char *, std::string const & );
226 static void check_source_directory_path_and_destination_directory_path ();
227 static void process_file ( boost::filesystem::path const & );
228 static bool is_valid_argument_array ( char **, int );
229 static void process_year_mode ( boost::filesystem::path const & );
230 static void process_lexical_mode ( boost::filesystem::path const & );
231 static void unlink_file ( boost::filesystem::path const & );
232 static std::string get_destination_file_name ( boost::filesystem::path const &, boost::filesystem::path const & );
233 static void process_month_mode ( boost::filesystem::path &, struct tm const & );
234 static void process_day_mode ( boost::filesystem::path &, struct tm const & );
235 static void process_hour_mode ( boost::filesystem::path &, struct tm const & );
236 static void process_minute_mode ( boost::filesystem::path &, struct tm const & );
237 static void process_second_mode ( boost::filesystem::path &, struct tm const & );
238 static void create_directory ( boost::filesystem::path const &, std::string const & );
239 static void link_or_copy_file ( boost::filesystem::path const &, boost::filesystem::path const & );
240 static void keep_same_accessed_time_and_modified_time ( boost::filesystem::path const &, boost::filesystem::path const & );
243 // Definition of main function
248 int const number_of_arguments,
249 char ** const argument_array
253 Home_Directory_Path = path_pointer_type ( new boost::filesystem::path ( std::getenv ( Home_Environment_Variable ) ) );
255 Extension_Configuration_File_Path = path_pointer_type ( new boost::filesystem::path ( get_extension_configuration_file_path () ) );
257 interpret_options ( number_of_arguments, argument_array );
259 read_extension_configuration_file ();
261 process_directory ( *Source_Directory_Path );
267 islib::normal_termination const &normal_termination
270 return normal_termination.get_exit_status ();
274 std::exception const &exception
277 islib::print_error_message ( std::string ( Program_Name ) + ": " + exception.what () );
283 islib::fatal_error const &fatal_error
286 char buffer [ BUFSIZ ];
287 char const *source = fatal_error.what ();
288 char *destination = buffer;
290 for ( ; *source; ++source, ++destination )
291 *destination = *source;
293 islib::write_assert ( STDERR_FILENO, buffer, BUFSIZ );
302 islib::print_error_message ( std::string ( Program_Name ) + ": unexpected exception." );
308 // Definition of static function
310 boost::filesystem::path
311 get_extension_configuration_file_path
315 boost::filesystem::path extension_configuration_file_path;
322 path_pointer_type const &home_directory_path,
323 boost::filesystem::path const &extension_configuration_file_path__
325 extension_configuration_file_path_ ( extension_configuration_file_path__ )
327 islib::throw_if ( std::logic_error ( "get_extension_configuration_file_path: !home_directory_path" ), !home_directory_path );
337 islib::assert_ ( !this->extension_configuration_file_path_.empty (), "get_extension_configuration_file_path: `!this->extension_configuration_file_path_.empty ()' has failed." );
341 boost::filesystem::path const &extension_configuration_file_path_;
343 local_ ( Home_Directory_Path, extension_configuration_file_path );
345 if ( !Home_Directory_Path->empty () )
346 extension_configuration_file_path = *Home_Directory_Path / Extension_Configuration_File_Name;
348 extension_configuration_file_path = boost::filesystem::path ( "." ) / Extension_Configuration_File_Name;
350 return extension_configuration_file_path;
354 // Definition of static function
359 int const number_of_arguments,
360 char ** const argument_array
368 int const number_of_arguments_,
369 char ** const argument_array_
372 islib::throw_if ( std::invalid_argument ( "interpret_options: number_of_arguments_ < 1" ), number_of_arguments_ < 1 );
373 islib::throw_if ( std::invalid_argument ( "interpret_options: !is_valid_argument_array ( argument_array_, number_of_arguments_ )" ), !is_valid_argument_array ( argument_array_, number_of_arguments_ ) );
385 local_ ( number_of_arguments, argument_array );
389 int option_index = 0;
391 int const option_character = getopt_long ( number_of_arguments, argument_array, Option_String, Long_Option_Array, &option_index );
393 if ( option_character == -1 )
396 switch ( option_character )
398 case Version_Option_Character:
399 print_version_message ();
401 throw islib::normal_termination ( EXIT_SUCCESS );
403 case Help_Option_Character:
404 print_help_message ();
406 throw islib::normal_termination ( EXIT_SUCCESS );
408 case Delete_Option_Character:
409 Delete_Mode_Flag = true;
413 case Hour_Option_Character:
414 Hour_Mode_Flag = true;
418 case Minute_Option_Character:
419 Minute_Mode_Flag = true;
423 case Second_Option_Character:
424 Second_Mode_Flag = true;
428 case Day_Option_Character:
429 Day_Mode_Flag = true;
433 case Lexical_Option_Character:
434 Lexical_Mode_Flag = true;
435 Lexical_Depth = get_lexical_depth ( optarg );
439 case Month_Option_Character:
440 Month_Mode_Flag = true;
444 case Recursive_Option_Character:
445 Recursive_Mode_Flag = true;
449 case Verbose_Option_Character:
450 Verbose_Mode_Flag = true;
454 case Year_Option_Character:
455 Year_Mode_Flag = true;
460 islib::throw_ ( std::logic_error ( "interpret_options: unexpected option." ) );
466 check_number_of_arguments ( number_of_arguments, argument_array, optind );
468 Source_Directory_Path = path_pointer_type ( new boost::filesystem::path ( get_directory_path ( argument_array [ optind ], "source" ) ) );
469 Destination_Directory_Path = path_pointer_type ( new boost::filesystem::path ( get_directory_path ( argument_array [ optind + 1 ], "destination" ) ) );
471 check_source_directory_path_and_destination_directory_path ();
475 // Definition of static function
478 read_extension_configuration_file
487 path_pointer_type const &extension_configuration_file_path
490 islib::throw_if ( std::logic_error ( "read_extension_configuration_file: !extension_configuration_file_path" ), !extension_configuration_file_path );
502 local_ ( Extension_Configuration_File_Path );
504 if ( !boost::filesystem::exists ( *Extension_Configuration_File_Path ) )
506 islib::print_error_message ( std::string ( Program_Name ) + ": extension configuration file `" + Extension_Configuration_File_Path->string () + "' does not exist." );
508 throw islib::normal_termination ( EXIT_FAILURE );
511 boost::filesystem::ifstream extension_configuration_file_stream ( *Extension_Configuration_File_Path );
513 if ( !extension_configuration_file_stream )
515 islib::print_error_message ( std::string ( Program_Name ) + ": opening extension configuration file `" + Extension_Configuration_File_Path->string () + "' has failed." );
517 throw islib::normal_termination ( EXIT_FAILURE );
522 Extension_Vector = string_vector_pointer_type ( new string_vector_type () );
524 while ( std::getline ( extension_configuration_file_stream, line ) )
526 std::string const extension ( islib::trim ( line ) );
528 if ( extension.empty () || extension [ 0 ] == Comment_Character )
531 if ( Verbose_Mode_Flag )
532 islib::print_message ( std::string ( Program_Name ) + ": extension `" + extension + "' has been included." );
534 Extension_Vector->push_back ( extension );
539 // Definition of static function
544 boost::filesystem::path const &directory_path
552 boost::filesystem::path const &directory_path_
555 islib::throw_if ( std::invalid_argument ( "process_directory: directory_path_.empty ()" ), directory_path_.empty () );
567 local_ ( directory_path );
569 for ( boost::filesystem::directory_iterator directory_iterator ( directory_path ); directory_iterator != boost::filesystem::directory_iterator (); ++directory_iterator )
571 boost::filesystem::path const &path ( *directory_iterator );
573 if ( path.leaf () [ 0 ] == '.' )
576 if ( boost::filesystem::is_directory ( path ) )
578 if ( Recursive_Mode_Flag )
579 process_directory ( path );
582 process_file ( path );
587 // Definition of static function
590 print_version_message
594 std::stringstream version_message_stream;
596 version_message_stream
597 << Program_Name << " " << Version << "\n"
598 << "Copyright (C) " << Copyright_Year << " " << Person_Entitiled_To_Copyright << "\n"
599 << Licence_Name << " <" << Licence_Url << ">\n"
600 << "This is free software: you are free to change and redistribute it.\n"
601 << "There is NO WARRANTY, to the extent permitted by law.\n"
603 << "Written by " << Writer_Name << "\n";
605 islib::print_message ( version_message_stream.str () );
609 // Definition of static function
616 std::stringstream help_message_stream;
619 << "Usage: " << Program_Name << " [option] source-directory destination-directory\n"
621 << "Link or copy files from source-directory to destination-directory.\n"
625 << " -" << Delete_Option_Character << ", --" << Delete_Option_String << "\n"
627 << " delete source file.\n"
630 << " -" << Hour_Option_Character << ", --" << Hour_Option_String << "\n"
632 << " create hour directories. need to specify -" << Day_Option_Character << " or --" << Day_Option_String << ".\n"
635 << " -" << Minute_Option_Character << ", --" << Minute_Option_String << "\n"
637 << " create minute directories. need to specify -" << Hour_Option_Character << " or --" << Hour_Option_String << ".\n"
640 << " -" << Second_Option_Character << ", --" << Second_Option_String << "\n"
642 << " create second directories. need to specify -" << Minute_Option_Character << " or --" << Minute_Option_String << ".\n"
645 << " -" << Version_Option_Character << ", --" << Version_Option_String << "\n"
647 << " print version message and exit.\n"
650 << " -" << Day_Option_Character << ", --" << Day_Option_String << "\n"
652 << " create day directories. need to specify -" << Month_Option_Character << " or --" << Month_Option_String << ".\n"
655 << " -" << Help_Option_Character << ", --" << Help_Option_String << "\n"
657 << " print this help message and exit.\n"
660 << " -" << Lexical_Option_Character << " N, --" << Lexical_Option_String << " N\n"
662 << " create lexical directories. N is lexical depth.\n"
665 << " -" << Month_Option_Character << ", --" << Month_Option_String << "\n"
667 << " create month directories. need to specify -" << Year_Option_Character << " or --" << Year_Option_String << ".\n"
670 << " -" << Recursive_Option_Character << ", --" << Recursive_Option_String << "\n"
672 << " do it at a directory below source-directory recursively.\n"
675 << " -" << Verbose_Option_Character << ", --" << Verbose_Option_String << "\n"
677 << " explain what is being done.\n"
680 << " -" << Year_Option_Character << ", --" << Year_Option_String << "\n"
682 << " create year directories.\n"
685 islib::print_message ( help_message_stream.str () );
689 // Definition of static function
694 char * const lexical_depth_string
702 char * const lexical_depth_string_
705 islib::throw_if ( std::invalid_argument ( "get_lexical_depth: !lexical_depth_string_" ), !lexical_depth_string_ );
706 islib::throw_if ( std::invalid_argument ( "get_lexical_depth: !*lexical_depth_string_" ), !*lexical_depth_string_ );
718 local_ ( lexical_depth_string );
720 std::size_t lexical_depth = 0;
724 lexical_depth = boost::lexical_cast < std::size_t > ( lexical_depth_string );
726 catch ( boost::bad_lexical_cast const &bad_lexical_cast )
728 std::stringstream error_message_stream;
731 << Program_Name << ": invalid lexical depth.\n"
732 << islib::get_try_help_message ( Program_Name );
734 islib::print_error_message ( error_message_stream.str () );
736 throw islib::normal_termination ( EXIT_FAILURE );
739 if ( lexical_depth == 0 )
741 std::stringstream error_message_stream;
744 << Program_Name << ": lexical depth is 0.\n"
745 << islib::get_try_help_message ( Program_Name );
747 islib::print_error_message ( error_message_stream.str () );
749 throw islib::normal_termination ( EXIT_FAILURE );
752 return lexical_depth;
756 // Definition of static function
763 if ( !Year_Mode_Flag && Month_Mode_Flag )
765 std::stringstream error_message_stream;
768 << Program_Name << ": -" << Month_Option_Character << " or --" << Month_Option_String << " is specified although -" << Year_Option_Character << " or --" << Year_Option_String << " is not specified.\n"
769 << islib::get_try_help_message ( Program_Name );
771 islib::print_error_message ( error_message_stream.str () );
773 throw islib::normal_termination ( EXIT_FAILURE );
776 if ( !Month_Mode_Flag && Day_Mode_Flag )
778 std::stringstream error_message_stream;
781 << Program_Name << ": -" << Day_Option_Character << " or --" << Day_Option_String << " is specified although -" << Month_Option_Character << " or --" << Month_Option_String << " is not specified.\n"
782 << islib::get_try_help_message ( Program_Name );
784 islib::print_error_message ( error_message_stream.str () );
786 throw islib::normal_termination ( EXIT_FAILURE );
789 if ( !Day_Mode_Flag && Hour_Mode_Flag )
791 std::stringstream error_message_stream;
794 << Program_Name << ": -" << Hour_Option_Character << " or --" << Hour_Option_String << " is specified although -" << Day_Option_Character << " or --" << Day_Option_String << " is not specified.\n"
795 << islib::get_try_help_message ( Program_Name );
797 islib::print_error_message ( error_message_stream.str () );
799 throw islib::normal_termination ( EXIT_FAILURE );
802 if ( !Hour_Mode_Flag && Minute_Mode_Flag )
804 std::stringstream error_message_stream;
807 << Program_Name << ": -" << Minute_Option_Character << " or --" << Minute_Option_String << " is specified although -" << Hour_Option_Character << " or --" << Hour_Option_String << " is not specified.\n"
808 << islib::get_try_help_message ( Program_Name );
810 islib::print_error_message ( error_message_stream.str () );
812 throw islib::normal_termination ( EXIT_FAILURE );
815 if ( !Minute_Mode_Flag && Second_Mode_Flag )
817 std::stringstream error_message_stream;
820 << Program_Name << ": -" << Second_Option_Character << " or --" << Second_Option_String << " is specified although -" << Minute_Option_Character << " or --" << Minute_Option_String << " is not specified.\n"
821 << islib::get_try_help_message ( Program_Name );
823 islib::print_error_message ( error_message_stream.str () );
825 throw islib::normal_termination ( EXIT_FAILURE );
830 // Definition of static function
833 check_number_of_arguments
835 int const number_of_arguments,
836 char ** const argument_array,
837 int const option_index
845 int const number_of_arguments_,
846 char ** const argument_array_,
847 int const option_index_
850 islib::throw_if ( std::invalid_argument ( "check_number_of_arguments: number_of_arguments_ < 1" ), number_of_arguments_ < 1 );
851 islib::throw_if ( std::invalid_argument ( "check_number_of_arguments: !is_valid_argument_array ( argument_array_, number_of_arguments_ )" ), !is_valid_argument_array ( argument_array_, number_of_arguments_ ) );
852 islib::throw_if ( std::invalid_argument ( "check_number_of_arguments: option_index_ < 1" ), option_index_ < 0 );
864 local_ ( number_of_arguments, argument_array, option_index );
866 if ( option_index + Number_Of_Static_Arguments < number_of_arguments )
868 std::stringstream error_message_stream;
870 error_message_stream << Program_Name << ( number_of_arguments - ( option_index + Number_Of_Static_Arguments ) == 1? ": unknown argument: `": ": unknown arguments: `" );
872 for ( int index_of_argument = option_index + Number_Of_Static_Arguments; index_of_argument != number_of_arguments; ++index_of_argument )
874 if ( index_of_argument != option_index + Number_Of_Static_Arguments )
875 error_message_stream << " ";
877 error_message_stream << argument_array [ index_of_argument ];
882 << islib::get_try_help_message ( Program_Name );
884 islib::print_error_message ( error_message_stream.str () );
886 throw islib::normal_termination ( EXIT_FAILURE );
888 else if ( option_index == number_of_arguments )
890 std::stringstream error_message_stream;
893 << Program_Name << ": source directory and destination directory are not specified.\n"
894 << islib::get_try_help_message ( Program_Name );
896 islib::print_error_message ( error_message_stream.str () );
898 throw islib::normal_termination ( EXIT_FAILURE );
900 else if ( option_index == number_of_arguments - 1 )
902 std::stringstream error_message_stream;
905 << Program_Name << ": destination directory is not specified.\n"
906 << islib::get_try_help_message ( Program_Name );
908 islib::print_error_message ( error_message_stream.str () );
910 throw islib::normal_termination ( EXIT_FAILURE );
915 // Definition of static function
917 boost::filesystem::path
920 char * const directory_path_string,
921 std::string const &kind_name_of_directory
924 boost::filesystem::path directory_path;
931 char * const directory_path_string_,
932 std::string const &kind_name_of_directory_,
933 boost::filesystem::path const &directory_path__
935 directory_path_ ( directory_path__ )
937 islib::throw_if ( std::invalid_argument ( "get_directory_path: !directory_path_string_" ), !directory_path_string_ );
938 islib::throw_if ( std::invalid_argument ( "get_directory_path: !*directory_path_string_" ), !*directory_path_string_ );
939 islib::throw_if ( std::invalid_argument ( "get_directory_path: kind_name_of_directory_.empty ()" ), kind_name_of_directory_.empty () );
949 islib::assert_ ( !this->directory_path_.empty (), "get_directory_path: `!this->directory_path_.empty ()' has failed." );
953 boost::filesystem::path const &directory_path_;
955 local_ ( directory_path_string, kind_name_of_directory, directory_path );
957 directory_path = directory_path_string;
959 if ( !boost::filesystem::exists ( directory_path ) )
961 islib::print_error_message ( std::string ( Program_Name ) + ": " + kind_name_of_directory + " directory `" + directory_path.string () + "' does not exist." );
963 throw islib::normal_termination ( EXIT_FAILURE );
966 if ( !boost::filesystem::is_directory ( directory_path ) )
968 std::stringstream error_message_stream;
971 << Program_Name << ": " << kind_name_of_directory << " directory `" << directory_path.string () << "' is not a directory.\n"
972 << islib::get_try_help_message ( Program_Name );
974 islib::print_error_message ( error_message_stream.str () );
976 throw islib::normal_termination ( EXIT_FAILURE );
979 return directory_path;
983 // Definition of static function
986 check_source_directory_path_and_destination_directory_path
995 path_pointer_type const &source_directory_path,
996 path_pointer_type const &destination_directory_path
999 islib::throw_if ( std::logic_error ( "check_source_directory_path_and_destination_directory_path: !source_directory_path" ), !source_directory_path );
1000 islib::throw_if ( std::logic_error ( "check_source_directory_path_and_destination_directory_path: !destination_directory_path" ), !destination_directory_path );
1012 local_ ( Source_Directory_Path, Destination_Directory_Path );
1014 if ( *Source_Directory_Path == *Destination_Directory_Path )
1016 islib::print_error_message ( std::string ( Program_Name ) + ": source directory `" + Source_Directory_Path->string () + "' and destination directory `" + Destination_Directory_Path->string () + "' equal to each other." );
1018 throw islib::normal_termination ( EXIT_FAILURE );
1021 struct stat source_directory_status;
1022 struct stat destination_directory_status;
1026 islib::stat_ ( *Source_Directory_Path, &source_directory_status );
1033 islib::print_error_message ( std::string ( Program_Name ) + ": getting directory `" + Source_Directory_Path->string () + "''s status has failed." );
1035 throw islib::normal_termination ( EXIT_FAILURE );
1040 islib::stat_ ( *Destination_Directory_Path, &destination_directory_status );
1047 islib::print_error_message ( std::string ( Program_Name ) + ": getting directory `" + Destination_Directory_Path->string () + "''s status has failed." );
1049 throw islib::normal_termination ( EXIT_FAILURE );
1052 if ( source_directory_status.st_dev == destination_directory_status.st_dev && source_directory_status.st_ino == destination_directory_status.st_ino )
1054 islib::print_error_message ( std::string ( Program_Name ) + ": source directory `" + Source_Directory_Path->string () + "' and destination directory `" + Destination_Directory_Path->string () + "' equal to each other." );
1056 throw islib::normal_termination ( EXIT_FAILURE );
1061 // Definition of static function
1066 boost::filesystem::path const &file_path
1074 boost::filesystem::path const &file_path_
1077 islib::throw_if ( std::invalid_argument ( "process_file: file_path_.empty ()" ), file_path_.empty () );
1089 local_ ( file_path );
1091 std::string const file_name ( file_path.leaf () );
1093 if ( file_name.find ( '.' ) != std::string::npos && std::find ( Extension_Vector->begin (), Extension_Vector->end (), boost::filesystem::extension ( file_path ) ) != Extension_Vector->end () )
1095 if ( Year_Mode_Flag || Lexical_Mode_Flag )
1097 if ( Year_Mode_Flag )
1098 process_year_mode ( file_path );
1100 if ( Lexical_Mode_Flag )
1101 process_lexical_mode ( file_path );
1104 link_or_copy_file ( file_path, *Destination_Directory_Path / file_name );
1107 if ( Delete_Mode_Flag )
1108 unlink_file ( file_path );
1112 // Definition of static function
1115 is_valid_argument_array
1117 char ** const argument_array,
1118 int const number_of_arguments
1121 if ( !argument_array )
1124 for ( int index_of_argument = 0; index_of_argument != number_of_arguments; ++index_of_argument )
1125 if ( !argument_array [ index_of_argument ] )
1132 // Definition of static function
1137 boost::filesystem::path const &source_file_path
1145 boost::filesystem::path const &source_file_path_
1148 islib::throw_if ( std::invalid_argument ( "process_year_mode: source_file_path_.empty ()" ), source_file_path_.empty () );
1160 local_ ( source_file_path );
1162 boost::filesystem::path destination_directory_path ( *Destination_Directory_Path );
1163 struct stat source_file_status_information;
1167 islib::stat_ ( source_file_path, &source_file_status_information );
1174 islib::print_error_message ( std::string ( Program_Name ) + ": getting file `" + source_file_path.string () + "''s status has failed." );
1176 throw islib::normal_termination ( EXIT_FAILURE );
1181 struct tm source_file_modified_time_information;
1185 islib::localtime_r_ ( &source_file_status_information.st_mtime, &source_file_modified_time_information );
1192 islib::print_error_message ( std::string ( Program_Name ) + ": converting time has failed." );
1194 throw islib::normal_termination ( EXIT_FAILURE );
1197 destination_directory_path /= boost::lexical_cast < std::string > ( source_file_modified_time_information.tm_year + 1900 );
1199 if ( !boost::filesystem::exists ( destination_directory_path ) )
1200 create_directory ( destination_directory_path, "year" );
1202 if ( Month_Mode_Flag )
1203 process_month_mode ( destination_directory_path, source_file_modified_time_information );
1205 std::string const destination_file_name ( get_destination_file_name ( source_file_path, destination_directory_path ) );
1207 if ( !destination_file_name.empty () )
1208 link_or_copy_file ( source_file_path, destination_directory_path / destination_file_name );
1212 // Definition of static function
1215 process_lexical_mode
1217 boost::filesystem::path const &source_file_path
1225 boost::filesystem::path const &source_file_path_
1228 islib::throw_if ( std::invalid_argument ( "process_lexical_mode: source_file_path_.empty ()" ), source_file_path_.empty () );
1240 local_ ( source_file_path );
1242 boost::filesystem::path destination_directory_path ( *Destination_Directory_Path );
1243 std::string const file_basename ( boost::filesystem::basename ( source_file_path ) );
1244 std::size_t const lexical_depth = std::min ( Lexical_Depth, file_basename.length () );
1246 for ( std::size_t index_of_file_basename = 0; index_of_file_basename != lexical_depth; ++index_of_file_basename )
1248 if ( !std::isgraph ( file_basename [ index_of_file_basename ] ) || file_basename [ index_of_file_basename ] == '.' )
1251 destination_directory_path /= std::string ( 1, file_basename [ index_of_file_basename ] );
1253 if ( !boost::filesystem::exists ( destination_directory_path ) )
1254 create_directory ( destination_directory_path, "lexical" );
1257 std::string const destination_file_name ( get_destination_file_name ( source_file_path, destination_directory_path ) );
1259 if ( !destination_file_name.empty () )
1260 link_or_copy_file ( source_file_path, destination_directory_path / destination_file_name );
1264 // Definition of static function
1269 boost::filesystem::path const &file_path
1277 boost::filesystem::path const &file_path_
1280 islib::throw_if ( std::invalid_argument ( "unlink_file: file_path_.empty ()" ), file_path_.empty () );
1292 local_ ( file_path );
1296 islib::unlink_ ( file_path );
1303 islib::print_error_message ( std::string ( Program_Name ) + ": unlinking file `" + file_path.string () + "' has failed." );
1305 throw islib::normal_termination ( EXIT_FAILURE );
1308 if ( Verbose_Mode_Flag )
1309 islib::print_message ( std::string ( Program_Name ) + ": file `" + file_path.string () + "' has been unlinked." );
1313 // Definition of static function
1315 // Return value: std::string (): there is identical file in destination_directory_path.
1318 get_destination_file_name
1320 boost::filesystem::path const &source_file_path,
1321 boost::filesystem::path const &destination_directory_path
1329 boost::filesystem::path const &source_file_path_,
1330 boost::filesystem::path const &destination_directory_path_
1333 islib::throw_if ( std::invalid_argument ( "get_destination_file_name: source_file_path_.empty ()" ), source_file_path_.empty () );
1334 islib::throw_if ( std::invalid_argument ( "get_destination_file_name: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1346 local_ ( source_file_path, destination_directory_path );
1348 std::string destination_file_name;
1349 std::size_t repetition_number = 0;
1351 destination_file_name = source_file_path.leaf ();
1353 while ( boost::filesystem::exists ( destination_directory_path / destination_file_name ) )
1355 if ( islib::binary_compare ( source_file_path, destination_directory_path / destination_file_name ) == 0 )
1356 return std::string ();
1358 if ( repetition_number == std::numeric_limits < std::size_t >::max () )
1360 islib::print_error_message ( std::string ( Program_Name ) + ": repetition number of file `" + source_file_path.string () + "' has overflowen." );
1362 throw islib::normal_termination ( EXIT_FAILURE );
1365 ++repetition_number;
1367 destination_file_name = boost::filesystem::basename ( source_file_path ) + " (" + boost::lexical_cast < std::string > ( repetition_number ) + ")" + boost::filesystem::extension ( source_file_path );
1370 return destination_file_name;
1374 // Definition of static function
1379 boost::filesystem::path &destination_directory_path,
1380 struct tm const &source_file_modified_time_information
1388 boost::filesystem::path const &destination_directory_path_
1391 islib::throw_if ( std::invalid_argument ( "process_month_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1403 local_ ( destination_directory_path );
1405 destination_directory_path /= ( boost::format ( "%02d" ) % ( source_file_modified_time_information.tm_mon + 1 ) ).str ();
1407 if ( !boost::filesystem::exists ( destination_directory_path ) )
1408 create_directory ( destination_directory_path, "month" );
1410 if ( Day_Mode_Flag )
1411 process_day_mode ( destination_directory_path, source_file_modified_time_information );
1415 // Definition of static function
1420 boost::filesystem::path &destination_directory_path,
1421 struct tm const &source_file_modified_time_information
1429 boost::filesystem::path const &destination_directory_path_
1432 islib::throw_if ( std::invalid_argument ( "process_day_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1444 local_ ( destination_directory_path );
1446 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_mday ).str ();
1448 if ( !boost::filesystem::exists ( destination_directory_path ) )
1449 create_directory ( destination_directory_path, "day" );
1451 if ( Hour_Mode_Flag )
1452 process_hour_mode ( destination_directory_path, source_file_modified_time_information );
1456 // Definition of static function
1461 boost::filesystem::path &destination_directory_path,
1462 struct tm const &source_file_modified_time_information
1470 boost::filesystem::path const &destination_directory_path_
1473 islib::throw_if ( std::invalid_argument ( "process_hour_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1485 local_ ( destination_directory_path );
1487 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_hour ).str ();
1489 if ( !boost::filesystem::exists ( destination_directory_path ) )
1490 create_directory ( destination_directory_path, "hour" );
1492 if ( Minute_Mode_Flag )
1493 process_minute_mode ( destination_directory_path, source_file_modified_time_information );
1497 // Definition of static function
1502 boost::filesystem::path &destination_directory_path,
1503 struct tm const &source_file_modified_time_information
1511 boost::filesystem::path const &destination_directory_path_
1514 islib::throw_if ( std::invalid_argument ( "process_minute_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1526 local_ ( destination_directory_path );
1528 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_min ).str ();
1530 if ( !boost::filesystem::exists ( destination_directory_path ) )
1531 create_directory ( destination_directory_path, "minute" );
1533 if ( Second_Mode_Flag )
1534 process_second_mode ( destination_directory_path, source_file_modified_time_information );
1538 // Definition of static function
1543 boost::filesystem::path &destination_directory_path,
1544 struct tm const &source_file_modified_time_information
1552 boost::filesystem::path const &destination_directory_path_
1555 islib::throw_if ( std::invalid_argument ( "process_second_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1567 local_ ( destination_directory_path );
1569 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_sec ).str ();
1571 if ( !boost::filesystem::exists ( destination_directory_path ) )
1572 create_directory ( destination_directory_path, "second" );
1576 // Definition of static function
1581 boost::filesystem::path const &directory_path,
1582 std::string const &kind_name_of_directory
1590 boost::filesystem::path const &directory_path_,
1591 std::string const &kind_name_of_directory_
1594 islib::throw_if ( std::invalid_argument ( "create_directory: directory_path_.empty ()" ), directory_path_.empty () );
1595 islib::throw_if ( std::invalid_argument ( "create_directory: kind_name_of_directory_.empty ()" ), kind_name_of_directory_.empty () );
1607 local_ ( directory_path, kind_name_of_directory );
1611 islib::mkdir_ ( directory_path, 0755 );
1618 islib::print_error_message ( std::string ( Program_Name ) + ": creating directory `" + directory_path.string () + "' has failed." );
1620 throw islib::normal_termination ( EXIT_FAILURE );
1623 if ( Verbose_Mode_Flag )
1624 islib::print_message ( std::string ( Program_Name ) + ": " + kind_name_of_directory + " directory `" + directory_path.string () + "' has been created." );
1628 // Definition of static function
1633 boost::filesystem::path const &source_file_path,
1634 boost::filesystem::path const &destination_file_path
1642 boost::filesystem::path const &source_file_path_,
1643 boost::filesystem::path const &destination_file_path_
1646 islib::throw_if ( std::invalid_argument ( "link_or_copy_file: source_file_path_.empty ()" ), source_file_path_.empty () );
1647 islib::throw_if ( std::invalid_argument ( "link_or_copy_file: destination_file_path_.empty ()" ), destination_file_path_.empty () );
1659 local_ ( source_file_path, destination_file_path );
1661 int link_return_value = link ( source_file_path.string ().c_str (), destination_file_path.string ().c_str () );
1663 if ( link_return_value != 0 )
1665 int const saved_errno = errno;
1667 if ( saved_errno == EPERM || saved_errno == EXDEV )
1671 boost::filesystem::copy_file ( source_file_path, destination_file_path );
1678 islib::print_error_message ( std::string ( Program_Name ) + ": copying file `" + source_file_path.string () + "' to `" + destination_file_path.string () + "' has failed." );
1680 throw islib::normal_termination ( EXIT_FAILURE );
1683 keep_same_accessed_time_and_modified_time ( source_file_path, destination_file_path );
1685 if ( Verbose_Mode_Flag )
1686 islib::print_message ( std::string ( Program_Name ) + ": file `" + source_file_path.string () + "' has been copied to `" + destination_file_path.string () + "'." );
1692 islib::print_error_message ( std::string ( Program_Name ) + ": linking file `" + source_file_path.string () + "' to `" + destination_file_path.string () + "' has failed." );
1694 throw islib::normal_termination ( EXIT_FAILURE );
1698 if ( Verbose_Mode_Flag )
1699 islib::print_message ( std::string ( Program_Name ) + ": file `" + source_file_path.string () + "' has been linked to `" + destination_file_path.string () + "'." );
1703 // Definition of static function
1706 keep_same_accessed_time_and_modified_time
1708 boost::filesystem::path const &source_file_path,
1709 boost::filesystem::path const &destination_file_path
1717 boost::filesystem::path const &source_file_path_,
1718 boost::filesystem::path const &destination_file_path_
1721 islib::throw_if ( std::invalid_argument ( "keep_same_accessed_time_and_modified_time: source_file_path_.empty ()" ), source_file_path_.empty () );
1722 islib::throw_if ( std::invalid_argument ( "keep_same_accessed_time_and_modified_time: destination_file_path_.empty ()" ), destination_file_path_.empty () );
1734 local_ ( source_file_path, destination_file_path );
1736 struct stat source_file_status_information;
1740 islib::stat_ ( source_file_path, &source_file_status_information );
1747 islib::print_error_message ( std::string ( Program_Name ) + ": getting file `" + source_file_path.string () + "''s status has failed." );
1749 throw islib::normal_termination ( EXIT_FAILURE );
1752 struct utimbuf utime_information;
1754 utime_information.actime = source_file_status_information.st_atime;
1755 utime_information.modtime = source_file_status_information.st_mtime;
1759 islib::utime_ ( destination_file_path, &utime_information );
1766 islib::print_error_message ( std::string ( Program_Name ) + ": setting file `" + source_file_path.string () + "''s accessed time and modified time has failed." );
1768 throw islib::normal_termination ( EXIT_FAILURE );