2 // Inclusion of standard header file
20 // Inclusion of system header file
27 // Inclusion of library header file
29 #include <boost/filesystem/convenience.hpp>
30 #include <boost/filesystem/fstream.hpp>
31 #include <boost/filesystem/operations.hpp>
32 #include <boost/filesystem/path.hpp>
33 #include <boost/format.hpp>
34 #include <boost/lexical_cast.hpp>
37 // Inclusion of local header file
39 #include "binary_compare.hpp"
40 #include "fatal_error.hpp"
41 #include "islibfunc.hpp"
42 #include "normal_termination.hpp"
43 #include "program.hpp"
44 #include "system_error.hpp"
50 typedef std::vector < std::string > string_vector_type;
53 // Definition of file scope static constant
55 static std::string const Program_Name ( "alstede" );
56 static std::string const Version ( "0.2.3" );
57 static int const Copyright_Year = 2009;
58 static std::string const Person_Entitiled_To_Copyright ( "I.S." );
59 static std::string const Licence_Name ( "License GPLv3+: GNU GPL version 3 or later" );
60 static std::string const Licence_Url ( "http://gnu.org/licenses/gpl.html" );
61 static std::string const Writer_Name ( "I.S." );
62 static std::string const Home_Environment_Variable ( "HOME" );
63 static int const Number_Of_Static_Arguments = 2;
64 static char const Delete_Option_Character = 'D';
65 static char const Hour_Option_Character = 'H';
66 static char const Minute_Option_Character = 'M';
67 static char const Second_Option_Character = 'S';
68 static char const Version_Option_Character = 'V';
69 static char const Day_Option_Character = 'd';
70 static char const Help_Option_Character = 'h';
71 static char const Lexical_Option_Character = 'l';
72 static char const Month_Option_Character = 'm';
73 static char const Recursive_Option_Character = 'r';
74 static char const Verbose_Option_Character = 'v';
75 static char const Year_Option_Character = 'y';
76 static char const Option_String [] =
78 Delete_Option_Character,
79 Hour_Option_Character,
80 Minute_Option_Character,
81 Second_Option_Character,
82 Version_Option_Character,
84 Help_Option_Character,
85 Lexical_Option_Character,
87 Month_Option_Character,
88 Recursive_Option_Character,
89 Verbose_Option_Character,
90 Year_Option_Character,
93 static char const * const Delete_Option_String = "delete";
94 static char const * const Hour_Option_String = "hour";
95 static char const * const Minute_Option_String = "minute";
96 static char const * const Second_Option_String = "second";
97 static char const * const Version_Option_String = "version";
98 static char const * const Day_Option_String = "day";
99 static char const * const Help_Option_String = "help";
100 static char const * const Lexical_Option_String = "lexical";
101 static char const * const Month_Option_String = "month";
102 static char const * const Recursive_Option_String = "recursive";
103 static char const * const Verbose_Option_String = "verbose";
104 static char const * const Year_Option_String = "year";
105 static struct option const Long_Option_Array [] =
108 Delete_Option_String,
111 Hour_Option_Character
117 Hour_Option_Character
120 Minute_Option_String,
123 Minute_Option_Character
126 Second_Option_String,
129 Second_Option_Character
132 Version_Option_String,
135 Second_Option_Character
147 Help_Option_Character
150 Lexical_Option_String,
153 Lexical_Option_Character
159 Month_Option_Character
162 Recursive_Option_String,
165 Recursive_Option_Character
168 Verbose_Option_String,
171 Verbose_Option_Character
177 Year_Option_Character
186 static std::string const Extension_Configuration_File_Name ( ".alstede_extensions" );
187 static char const Comment_Character = '#';
190 // Declaration of file scope static variable
192 static boost::filesystem::path Home_Directory_Path;
193 static boost::filesystem::path Extension_Configuration_File_Path;
194 static bool Delete_Mode_Flag = false;
195 static bool Year_Mode_Flag = false;
196 static bool Month_Mode_Flag = false;
197 static bool Day_Mode_Flag = false;
198 static bool Hour_Mode_Flag = false;
199 static bool Minute_Mode_Flag = false;
200 static bool Second_Mode_Flag = false;
201 static bool Lexical_Mode_Flag = false;
202 static bool Recursive_Mode_Flag = false;
203 static bool Verbose_Mode_Flag = false;
204 static std::size_t Lexical_Depth = 0;
205 static boost::filesystem::path Source_Directory_Path;
206 static boost::filesystem::path Destination_Directory_Path;
207 static string_vector_type Extension_Vector;
210 // Declaration of static function
212 static boost::filesystem::path get_extension_configuration_file_path ();
213 static void interpret_options ( int, char ** );
214 static void read_extension_configuration_file ();
215 static void process_directory ( boost::filesystem::path const & );
216 static void print_version_message ();
217 static void print_help_message ();
218 static std::size_t get_lexical_depth ( char * );
219 static void check_flags ();
220 static void check_number_of_arguments ( int, char **, int );
221 static boost::filesystem::path get_directory_path ( char *, std::string const & );
222 static void check_source_directory_path_and_destination_directory_path ();
223 static void process_file ( boost::filesystem::path const & );
224 static bool is_valid_argument_array ( char **, int );
225 static void process_year_mode ( boost::filesystem::path const & );
226 static void process_lexical_mode ( boost::filesystem::path const & );
227 static void unlink_file ( boost::filesystem::path const & );
228 static std::string get_destination_file_name ( boost::filesystem::path const &, boost::filesystem::path const & );
229 static void process_month_mode ( boost::filesystem::path &, struct tm const & );
230 static void process_day_mode ( boost::filesystem::path &, struct tm const & );
231 static void process_hour_mode ( boost::filesystem::path &, struct tm const & );
232 static void process_minute_mode ( boost::filesystem::path &, struct tm const & );
233 static void process_second_mode ( boost::filesystem::path &, struct tm const & );
234 static void create_directory ( boost::filesystem::path const &, std::string const & );
235 static void link_or_copy_file ( boost::filesystem::path const &, boost::filesystem::path const & );
236 static void keep_same_accessed_time_and_modified_time ( boost::filesystem::path const &, boost::filesystem::path const & );
239 // Definition of main function
244 int const number_of_arguments,
245 char ** const argument_array
249 Home_Directory_Path = std::getenv ( Home_Environment_Variable.c_str () );
251 Extension_Configuration_File_Path = get_extension_configuration_file_path ();
253 interpret_options ( number_of_arguments, argument_array );
255 read_extension_configuration_file ();
257 process_directory ( Source_Directory_Path );
263 islib::normal_termination const &normal_termination
266 return normal_termination.get_exit_status ();
270 std::exception const &exception
273 islib::print_error_message ( Program_Name + ": " + exception.what () );
279 islib::fatal_error const &fatal_error
282 char buffer [ BUFSIZ ];
283 char const *source = fatal_error.what ();
284 char *destination = buffer;
286 for ( ; *source; ++source, ++destination )
287 *destination = *source;
289 islib::write_assert ( STDERR_FILENO, buffer, BUFSIZ );
298 islib::print_error_message ( Program_Name + ": unexpected exception." );
304 // Definition of static function
306 boost::filesystem::path
307 get_extension_configuration_file_path
311 boost::filesystem::path extension_configuration_file_path;
318 boost::filesystem::path const &extension_configuration_file_path__
320 extension_configuration_file_path_ ( extension_configuration_file_path__ )
331 islib::assert_ ( !this->extension_configuration_file_path_.empty (), "get_extension_configuration_file_path: `!this->extension_configuration_file_path_.empty ()' has failed." );
335 boost::filesystem::path const &extension_configuration_file_path_;
337 local_ ( extension_configuration_file_path );
339 if ( !Home_Directory_Path.empty () )
340 extension_configuration_file_path = Home_Directory_Path / Extension_Configuration_File_Name;
342 extension_configuration_file_path = boost::filesystem::path ( "." ) / Extension_Configuration_File_Name;
344 return extension_configuration_file_path;
348 // Definition of static function
353 int const number_of_arguments,
354 char ** const argument_array
362 int const number_of_arguments_,
363 char ** const argument_array_
366 islib::throw_if ( std::invalid_argument ( "interpret_options: number_of_arguments_ < 1" ), number_of_arguments_ < 1 );
367 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_ ) );
379 local_ ( number_of_arguments, argument_array );
383 int option_index = 0;
385 int const option_character = getopt_long ( number_of_arguments, argument_array, Option_String, Long_Option_Array, &option_index );
387 if ( option_character == -1 )
390 switch ( option_character )
392 case Version_Option_Character:
393 print_version_message ();
395 throw islib::normal_termination ( EXIT_SUCCESS );
397 case Help_Option_Character:
398 print_help_message ();
400 throw islib::normal_termination ( EXIT_SUCCESS );
402 case Delete_Option_Character:
403 Delete_Mode_Flag = true;
407 case Hour_Option_Character:
408 Hour_Mode_Flag = true;
412 case Minute_Option_Character:
413 Minute_Mode_Flag = true;
417 case Second_Option_Character:
418 Second_Mode_Flag = true;
422 case Day_Option_Character:
423 Day_Mode_Flag = true;
427 case Lexical_Option_Character:
428 Lexical_Mode_Flag = true;
429 Lexical_Depth = get_lexical_depth ( optarg );
433 case Month_Option_Character:
434 Month_Mode_Flag = true;
438 case Recursive_Option_Character:
439 Recursive_Mode_Flag = true;
443 case Verbose_Option_Character:
444 Verbose_Mode_Flag = true;
448 case Year_Option_Character:
449 Year_Mode_Flag = true;
454 islib::throw_ ( std::logic_error ( "interpret_options: unexpected option." ) );
460 check_number_of_arguments ( number_of_arguments, argument_array, optind );
462 Source_Directory_Path = get_directory_path ( argument_array [ optind ], "source" );
463 Destination_Directory_Path = get_directory_path ( argument_array [ optind + 1 ], "destination" );
465 check_source_directory_path_and_destination_directory_path ();
469 // Definition of static function
472 read_extension_configuration_file
476 if ( !boost::filesystem::exists ( Extension_Configuration_File_Path ) )
478 islib::print_error_message ( Program_Name + ": extension configuration file `" + Extension_Configuration_File_Path.string () + "' does not exist." );
480 throw islib::normal_termination ( EXIT_FAILURE );
483 boost::filesystem::ifstream extension_configuration_file_stream ( Extension_Configuration_File_Path );
485 if ( !extension_configuration_file_stream )
487 islib::print_error_message ( Program_Name + ": opening extension configuration file `" + Extension_Configuration_File_Path.string () + "' has failed." );
489 throw islib::normal_termination ( EXIT_FAILURE );
494 while ( std::getline ( extension_configuration_file_stream, line ) )
496 std::string const extension ( islib::trim ( line ) );
498 if ( extension.empty () || extension [ 0 ] == Comment_Character )
501 if ( Verbose_Mode_Flag )
502 islib::print_message ( Program_Name + ": extension `" + extension + "' has been included." );
504 Extension_Vector.push_back ( extension );
509 // Definition of static function
514 boost::filesystem::path const &directory_path
522 boost::filesystem::path const &directory_path_
525 islib::throw_if ( std::invalid_argument ( "process_directory: directory_path_.empty ()" ), directory_path_.empty () );
537 local_ ( directory_path );
539 for ( boost::filesystem::directory_iterator directory_iterator ( directory_path ); directory_iterator != boost::filesystem::directory_iterator (); ++directory_iterator )
541 boost::filesystem::path const &path ( *directory_iterator );
543 if ( path.leaf () [ 0 ] == '.' )
546 if ( boost::filesystem::is_directory ( path ) )
548 if ( Recursive_Mode_Flag )
549 process_directory ( path );
552 process_file ( path );
557 // Definition of static function
560 print_version_message
564 std::stringstream version_message_stream;
566 version_message_stream
567 << Program_Name << " " << Version << "\n"
568 << "Copyright (C) " << Copyright_Year << " " << Person_Entitiled_To_Copyright << "\n"
569 << Licence_Name << " <" << Licence_Url << ">\n"
570 << "This is free software: you are free to change and redistribute it.\n"
571 << "There is NO WARRANTY, to the extent permitted by law.\n"
573 << "Written by " << Writer_Name << "\n";
575 islib::print_message ( version_message_stream.str () );
579 // Definition of static function
586 std::stringstream help_message_stream;
589 << "Usage: " << Program_Name << " [option] source-directory destination-directory\n"
591 << "Link or copy files from source-directory to destination-directory.\n"
594 << " -" << Delete_Option_Character << ", --" << Delete_Option_String << ": delete source file.\n"
595 << " -" << Hour_Option_Character << ", --" << Hour_Option_String << ": create hour directories. need to specify -" << Day_Option_Character << " or --" << Day_Option_String << ".\n"
596 << " -" << Minute_Option_Character << ", --" << Minute_Option_String << ": create minute directories. need to specify -" << Hour_Option_Character << " or --" << Hour_Option_String << ".\n"
597 << " -" << Second_Option_Character << ", --" << Second_Option_String << ": create second directories. need to specify -" << Minute_Option_Character << " or --" << Minute_Option_String << ".\n"
598 << " -" << Version_Option_Character << ", --" << Version_Option_String << ": print version message and exit.\n"
599 << " -" << Day_Option_Character << ", --" << Day_Option_String << ": create day directories. need to specify -" << Month_Option_Character << " or --" << Month_Option_String << ".\n"
600 << " -" << Help_Option_Character << ", --" << Help_Option_String << ": print this help message and exit.\n"
601 << " -" << Lexical_Option_Character << " N, --" << Lexical_Option_String << " N: create lexical directories. N is lexical depth.\n"
602 << " -" << Month_Option_Character << ", --" << Month_Option_String << ": create month directories. need to specify -" << Year_Option_Character << " or --" << Year_Option_String << ".\n"
603 << " -" << Recursive_Option_Character << ", --" << Recursive_Option_String << ": do it at a directory below source-directory recursively.\n"
604 << " -" << Verbose_Option_Character << ", --" << Verbose_Option_String << ": explain what is being done.\n"
605 << " -" << Year_Option_Character << ", --" << Year_Option_String << ": create year directories.";
607 islib::print_message ( help_message_stream.str () );
611 // Definition of static function
616 char * const lexical_depth_string
624 char * const lexical_depth_string_
627 islib::throw_if ( std::invalid_argument ( "get_lexical_depth: !lexical_depth_string_" ), !lexical_depth_string_ );
628 islib::throw_if ( std::invalid_argument ( "get_lexical_depth: *lexical_depth_string_ == 0" ), *lexical_depth_string_ == 0 );
640 local_ ( lexical_depth_string );
642 std::size_t lexical_depth = 0;
646 lexical_depth = boost::lexical_cast < std::size_t > ( lexical_depth_string );
648 catch ( boost::bad_lexical_cast const &bad_lexical_cast )
650 std::stringstream error_message_stream;
653 << Program_Name << ": invalid lexical depth.\n"
654 << islib::get_try_help_message ( Program_Name );
656 islib::print_error_message ( error_message_stream.str () );
658 throw islib::normal_termination ( EXIT_FAILURE );
661 if ( lexical_depth == 0 )
663 std::stringstream error_message_stream;
666 << Program_Name << ": lexical depth is 0.\n"
667 << islib::get_try_help_message ( Program_Name );
669 islib::print_error_message ( error_message_stream.str () );
671 throw islib::normal_termination ( EXIT_FAILURE );
674 return lexical_depth;
678 // Definition of static function
685 if ( !Year_Mode_Flag && Month_Mode_Flag )
687 std::stringstream error_message_stream;
690 << Program_Name << ": -" << Month_Option_Character << " or --" << Month_Option_String << " is specified although -" << Year_Option_Character << " or --" << Year_Option_String << " is not specified.\n"
691 << islib::get_try_help_message ( Program_Name );
693 islib::print_error_message ( error_message_stream.str () );
695 throw islib::normal_termination ( EXIT_FAILURE );
698 if ( !Month_Mode_Flag && Day_Mode_Flag )
700 std::stringstream error_message_stream;
703 << Program_Name << ": -" << Day_Option_Character << " or --" << Day_Option_String << " is specified although -" << Month_Option_Character << " or --" << Month_Option_String << " is not specified.\n"
704 << islib::get_try_help_message ( Program_Name );
706 islib::print_error_message ( error_message_stream.str () );
708 throw islib::normal_termination ( EXIT_FAILURE );
711 if ( !Day_Mode_Flag && Hour_Mode_Flag )
713 std::stringstream error_message_stream;
716 << Program_Name << ": -" << Hour_Option_Character << " or --" << Hour_Option_String << " is specified although -" << Day_Option_Character << " or --" << Day_Option_String << " is not specified.\n"
717 << islib::get_try_help_message ( Program_Name );
719 islib::print_error_message ( error_message_stream.str () );
721 throw islib::normal_termination ( EXIT_FAILURE );
724 if ( !Hour_Mode_Flag && Minute_Mode_Flag )
726 std::stringstream error_message_stream;
729 << Program_Name << ": -" << Minute_Option_Character << " or --" << Minute_Option_String << " is specified although -" << Hour_Option_Character << " or --" << Hour_Option_String << " is not specified.\n"
730 << islib::get_try_help_message ( Program_Name );
732 islib::print_error_message ( error_message_stream.str () );
734 throw islib::normal_termination ( EXIT_FAILURE );
737 if ( !Minute_Mode_Flag && Second_Mode_Flag )
739 std::stringstream error_message_stream;
742 << Program_Name << ": -" << Second_Option_Character << " or --" << Second_Option_String << " is specified although -" << Minute_Option_Character << " or --" << Minute_Option_String << " is not specified.\n"
743 << islib::get_try_help_message ( Program_Name );
745 islib::print_error_message ( error_message_stream.str () );
747 throw islib::normal_termination ( EXIT_FAILURE );
752 // Definition of static function
755 check_number_of_arguments
757 int const number_of_arguments,
758 char ** const argument_array,
759 int const option_index
767 int const number_of_arguments_,
768 char ** const argument_array_,
769 int const option_index_
772 islib::throw_if ( std::invalid_argument ( "check_number_of_arguments: number_of_arguments_ < 1" ), number_of_arguments_ < 1 );
773 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_ ) );
774 islib::throw_if ( std::invalid_argument ( "check_number_of_arguments: option_index_ < 1" ), option_index_ < 0 );
786 local_ ( number_of_arguments, argument_array, option_index );
788 if ( option_index + Number_Of_Static_Arguments < number_of_arguments )
790 std::stringstream error_message_stream;
792 error_message_stream << Program_Name << ( number_of_arguments - ( option_index + Number_Of_Static_Arguments ) == 1? ": unknown argument: `": ": unknown arguments: `" );
794 for ( int index_of_argument = option_index + Number_Of_Static_Arguments; index_of_argument != number_of_arguments; ++index_of_argument )
796 if ( index_of_argument != option_index + Number_Of_Static_Arguments )
797 error_message_stream << " ";
799 error_message_stream << argument_array [ index_of_argument ];
804 << islib::get_try_help_message ( Program_Name );
806 islib::print_error_message ( error_message_stream.str () );
808 throw islib::normal_termination ( EXIT_FAILURE );
810 else if ( option_index == number_of_arguments )
812 std::stringstream error_message_stream;
815 << Program_Name << ": source directory and destination directory are not specified.\n"
816 << islib::get_try_help_message ( Program_Name );
818 islib::print_error_message ( error_message_stream.str () );
820 throw islib::normal_termination ( EXIT_FAILURE );
822 else if ( option_index == number_of_arguments - 1 )
824 std::stringstream error_message_stream;
827 << Program_Name << ": destination directory is not specified.\n"
828 << islib::get_try_help_message ( Program_Name );
830 islib::print_error_message ( error_message_stream.str () );
832 throw islib::normal_termination ( EXIT_FAILURE );
837 // Definition of static function
839 boost::filesystem::path
842 char * const directory_path_string,
843 std::string const &kind_name_of_directory
846 boost::filesystem::path directory_path;
853 char * const directory_path_string_,
854 std::string const &kind_name_of_directory_,
855 boost::filesystem::path const &directory_path__
857 directory_path_ ( directory_path__ )
859 islib::throw_if ( std::invalid_argument ( "get_directory_path: !directory_path_string_" ), !directory_path_string_ );
860 islib::throw_if ( std::invalid_argument ( "get_directory_path: *directory_path_string_ == 0" ), *directory_path_string_ == 0 );
861 islib::throw_if ( std::invalid_argument ( "get_directory_path: kind_name_of_directory_.empty ()" ), kind_name_of_directory_.empty () );
871 islib::assert_ ( !this->directory_path_.empty (), "get_directory_path: `!this->directory_path_.empty ()' has failed." );
875 boost::filesystem::path const &directory_path_;
877 local_ ( directory_path_string, kind_name_of_directory, directory_path );
879 directory_path = directory_path_string;
881 if ( !boost::filesystem::exists ( directory_path ) )
883 islib::print_error_message ( Program_Name + ": " + kind_name_of_directory + " directory `" + directory_path.string () + "' does not exist." );
885 throw islib::normal_termination ( EXIT_FAILURE );
888 if ( !boost::filesystem::is_directory ( directory_path ) )
890 std::stringstream error_message_stream;
893 << Program_Name << ": " << kind_name_of_directory << " directory `" << directory_path.string () << "' is not a directory.\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 );
901 return directory_path;
905 // Definition of static function
908 check_source_directory_path_and_destination_directory_path
912 if ( Source_Directory_Path == Destination_Directory_Path )
914 islib::print_error_message ( Program_Name + ": source directory `" + Source_Directory_Path.string () + "' and destination directory `" + Destination_Directory_Path.string () + "' equal to each other." );
916 throw islib::normal_termination ( EXIT_FAILURE );
919 struct stat source_directory_status;
920 struct stat destination_directory_status;
922 islib::stat_ ( Source_Directory_Path, &source_directory_status );
923 islib::stat_ ( Destination_Directory_Path, &destination_directory_status );
925 if ( source_directory_status.st_dev == destination_directory_status.st_dev && source_directory_status.st_ino == destination_directory_status.st_ino )
927 islib::print_error_message ( Program_Name + ": source directory `" + Source_Directory_Path.string () + "' and destination directory `" + Destination_Directory_Path.string () + "' equal to each other." );
929 throw islib::normal_termination ( EXIT_FAILURE );
934 // Definition of static function
939 boost::filesystem::path const &file_path
947 boost::filesystem::path const &file_path_
950 islib::throw_if ( std::invalid_argument ( "process_file: file_path_.empty ()" ), file_path_.empty () );
962 local_ ( file_path );
964 std::string const file_name ( file_path.leaf () );
966 if ( file_name.find ( '.' ) != std::string::npos && std::find ( Extension_Vector.begin (), Extension_Vector.end (), boost::filesystem::extension ( file_path ) ) != Extension_Vector.end () )
968 if ( Year_Mode_Flag || Lexical_Mode_Flag )
970 if ( Year_Mode_Flag )
971 process_year_mode ( file_path );
973 if ( Lexical_Mode_Flag )
974 process_lexical_mode ( file_path );
977 link_or_copy_file ( file_path, Destination_Directory_Path / file_name );
980 if ( Delete_Mode_Flag )
981 unlink_file ( file_path );
985 // Definition of static function
988 is_valid_argument_array
990 char ** const argument_array,
991 int const number_of_arguments
994 if ( !argument_array )
997 for ( int index_of_argument = 0; index_of_argument != number_of_arguments; ++index_of_argument )
998 if ( !argument_array [ index_of_argument ] )
1005 // Definition of static function
1010 boost::filesystem::path const &source_file_path
1018 boost::filesystem::path const &source_file_path_
1021 islib::throw_if ( std::invalid_argument ( "process_year_mode: source_file_path_.empty ()" ), source_file_path_.empty () );
1033 local_ ( source_file_path );
1035 boost::filesystem::path destination_directory_path ( Destination_Directory_Path );
1036 struct stat source_file_status_information;
1038 islib::stat_ ( source_file_path, &source_file_status_information );
1042 struct tm source_file_modified_time_information;
1044 islib::localtime_r_ ( &source_file_status_information.st_mtime, &source_file_modified_time_information );
1046 destination_directory_path /= boost::lexical_cast < std::string > ( source_file_modified_time_information.tm_year + 1900 );
1048 if ( !boost::filesystem::exists ( destination_directory_path ) )
1049 create_directory ( destination_directory_path, "year" );
1051 if ( Month_Mode_Flag )
1052 process_month_mode ( destination_directory_path, source_file_modified_time_information );
1054 std::string const destination_file_name ( get_destination_file_name ( source_file_path, destination_directory_path ) );
1056 if ( !destination_file_name.empty () )
1057 link_or_copy_file ( source_file_path, destination_directory_path / destination_file_name );
1061 // Definition of static function
1064 process_lexical_mode
1066 boost::filesystem::path const &source_file_path
1074 boost::filesystem::path const &source_file_path_
1077 islib::throw_if ( std::invalid_argument ( "process_lexical_mode: source_file_path_.empty ()" ), source_file_path_.empty () );
1089 local_ ( source_file_path );
1091 boost::filesystem::path destination_directory_path ( Destination_Directory_Path );
1092 std::string const file_basename ( boost::filesystem::basename ( source_file_path ) );
1093 std::size_t const lexical_depth = std::min ( Lexical_Depth, file_basename.length () );
1095 for ( std::size_t index_of_file_basename = 0; index_of_file_basename != lexical_depth; ++index_of_file_basename )
1097 if ( !std::isgraph ( file_basename [ index_of_file_basename ] ) || file_basename [ index_of_file_basename ] == '.' )
1100 destination_directory_path /= std::string ( 1, file_basename [ index_of_file_basename ] );
1102 if ( !boost::filesystem::exists ( destination_directory_path ) )
1103 create_directory ( destination_directory_path, "lexical" );
1106 std::string const destination_file_name ( get_destination_file_name ( source_file_path, destination_directory_path ) );
1108 if ( !destination_file_name.empty () )
1109 link_or_copy_file ( source_file_path, destination_directory_path / destination_file_name );
1113 // Definition of static function
1118 boost::filesystem::path const &file_path
1126 boost::filesystem::path const &file_path_
1129 islib::throw_if ( std::invalid_argument ( "unlink_file: file_path_.empty ()" ), file_path_.empty () );
1141 local_ ( file_path );
1145 islib::unlink_ ( file_path );
1152 islib::print_error_message ( Program_Name + ": unlinking file `" + file_path.string () + "' has failed." );
1154 throw islib::normal_termination ( EXIT_FAILURE );
1157 if ( Verbose_Mode_Flag )
1158 islib::print_message ( Program_Name + ": file `" + file_path.string () + "' has been unlinked." );
1162 // Definition of static function
1164 // Return value: std::string (): there is identical file in destination_directory_path.
1167 get_destination_file_name
1169 boost::filesystem::path const &source_file_path,
1170 boost::filesystem::path const &destination_directory_path
1178 boost::filesystem::path const &source_file_path_,
1179 boost::filesystem::path const &destination_directory_path_
1182 islib::throw_if ( std::invalid_argument ( "get_destination_file_name: source_file_path_.empty ()" ), source_file_path_.empty () );
1183 islib::throw_if ( std::invalid_argument ( "get_destination_file_name: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1195 local_ ( source_file_path, destination_directory_path );
1197 std::string destination_file_name;
1198 std::size_t repetition_number = 0;
1200 destination_file_name = source_file_path.leaf ();
1202 while ( boost::filesystem::exists ( destination_directory_path / destination_file_name ) )
1204 if ( islib::binary_compare ( source_file_path, destination_directory_path / destination_file_name ) == 0 )
1205 return std::string ();
1207 if ( repetition_number == std::numeric_limits < std::size_t >::max () )
1209 islib::print_error_message ( Program_Name + ": repetition number of file `" + source_file_path.string () + "' has overflowen." );
1211 throw islib::normal_termination ( EXIT_FAILURE );
1214 ++repetition_number;
1216 destination_file_name = boost::filesystem::basename ( source_file_path ) + " (" + boost::lexical_cast < std::string > ( repetition_number ) + ")" + boost::filesystem::extension ( source_file_path );
1219 return destination_file_name;
1223 // Definition of static function
1228 boost::filesystem::path &destination_directory_path,
1229 struct tm const &source_file_modified_time_information
1237 boost::filesystem::path const &destination_directory_path_
1240 islib::throw_if ( std::invalid_argument ( "process_month_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1252 local_ ( destination_directory_path );
1254 destination_directory_path /= ( boost::format ( "%02d" ) % ( source_file_modified_time_information.tm_mon + 1 ) ).str ();
1256 if ( !boost::filesystem::exists ( destination_directory_path ) )
1257 create_directory ( destination_directory_path, "month" );
1259 if ( Day_Mode_Flag )
1260 process_day_mode ( destination_directory_path, source_file_modified_time_information );
1264 // Definition of static function
1269 boost::filesystem::path &destination_directory_path,
1270 struct tm const &source_file_modified_time_information
1278 boost::filesystem::path const &destination_directory_path_
1281 islib::throw_if ( std::invalid_argument ( "process_day_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1293 local_ ( destination_directory_path );
1295 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_mday ).str ();
1297 if ( !boost::filesystem::exists ( destination_directory_path ) )
1298 create_directory ( destination_directory_path, "day" );
1300 if ( Hour_Mode_Flag )
1301 process_hour_mode ( destination_directory_path, source_file_modified_time_information );
1305 // Definition of static function
1310 boost::filesystem::path &destination_directory_path,
1311 struct tm const &source_file_modified_time_information
1319 boost::filesystem::path const &destination_directory_path_
1322 islib::throw_if ( std::invalid_argument ( "process_hour_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1334 local_ ( destination_directory_path );
1336 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_hour ).str ();
1338 if ( !boost::filesystem::exists ( destination_directory_path ) )
1339 create_directory ( destination_directory_path, "hour" );
1341 if ( Minute_Mode_Flag )
1342 process_minute_mode ( destination_directory_path, source_file_modified_time_information );
1346 // Definition of static function
1351 boost::filesystem::path &destination_directory_path,
1352 struct tm const &source_file_modified_time_information
1360 boost::filesystem::path const &destination_directory_path_
1363 islib::throw_if ( std::invalid_argument ( "process_minute_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1375 local_ ( destination_directory_path );
1377 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_min ).str ();
1379 if ( !boost::filesystem::exists ( destination_directory_path ) )
1380 create_directory ( destination_directory_path, "minute" );
1382 if ( Second_Mode_Flag )
1383 process_second_mode ( destination_directory_path, source_file_modified_time_information );
1387 // Definition of static function
1392 boost::filesystem::path &destination_directory_path,
1393 struct tm const &source_file_modified_time_information
1401 boost::filesystem::path const &destination_directory_path_
1404 islib::throw_if ( std::invalid_argument ( "process_second_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1416 local_ ( destination_directory_path );
1418 destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_sec ).str ();
1420 if ( !boost::filesystem::exists ( destination_directory_path ) )
1421 create_directory ( destination_directory_path, "second" );
1425 // Definition of static function
1430 boost::filesystem::path const &directory_path,
1431 std::string const &kind_name_of_directory
1439 boost::filesystem::path const &directory_path_,
1440 std::string const &kind_name_of_directory_
1443 islib::throw_if ( std::invalid_argument ( "create_directory: directory_path_.empty ()" ), directory_path_.empty () );
1444 islib::throw_if ( std::invalid_argument ( "create_directory: kind_name_of_directory_.empty ()" ), kind_name_of_directory_.empty () );
1456 local_ ( directory_path, kind_name_of_directory );
1460 islib::mkdir_ ( directory_path, 0755 );
1467 islib::print_error_message ( Program_Name + ": creating directory `" + directory_path.string () + "' has failed." );
1469 throw islib::normal_termination ( EXIT_FAILURE );
1472 if ( Verbose_Mode_Flag )
1473 islib::print_message ( Program_Name + ": " + kind_name_of_directory + " directory `" + directory_path.string () + "' has been created." );
1477 // Definition of static function
1482 boost::filesystem::path const &source_file_path,
1483 boost::filesystem::path const &destination_file_path
1491 boost::filesystem::path const &source_file_path_,
1492 boost::filesystem::path const &destination_file_path_
1495 islib::throw_if ( std::invalid_argument ( "link_or_copy_file: source_file_path_.empty ()" ), source_file_path_.empty () );
1496 islib::throw_if ( std::invalid_argument ( "link_or_copy_file: destination_file_path_.empty ()" ), destination_file_path_.empty () );
1508 local_ ( source_file_path, destination_file_path );
1510 int link_return_value = link ( source_file_path.string ().c_str (), destination_file_path.string ().c_str () );
1512 if ( link_return_value != 0 )
1514 int const saved_errno = errno;
1516 if ( saved_errno == EPERM || saved_errno == EXDEV )
1520 boost::filesystem::copy_file ( source_file_path, destination_file_path );
1527 islib::print_error_message ( Program_Name + ": copying file `" + source_file_path.string () + "' to `" + destination_file_path.string () + "' has failed." );
1529 throw islib::normal_termination ( EXIT_FAILURE );
1532 keep_same_accessed_time_and_modified_time ( source_file_path, destination_file_path );
1534 if ( Verbose_Mode_Flag )
1535 islib::print_message ( Program_Name + ": file `" + source_file_path.string () + "' has been copied to `" + destination_file_path.string () + "'." );
1541 islib::print_error_message ( Program_Name + ": linking file `" + source_file_path.string () + "' to `" + destination_file_path.string () + "' has failed." );
1543 throw islib::normal_termination ( EXIT_FAILURE );
1547 if ( Verbose_Mode_Flag )
1548 islib::print_message ( Program_Name + ": file `" + source_file_path.string () + "' has been linked to `" + destination_file_path.string () + "'." );
1552 // Definition of static function
1555 keep_same_accessed_time_and_modified_time
1557 boost::filesystem::path const &source_file_path,
1558 boost::filesystem::path const &destination_file_path
1566 boost::filesystem::path const &source_file_path_,
1567 boost::filesystem::path const &destination_file_path_
1570 islib::throw_if ( std::invalid_argument ( "keep_same_accessed_time_and_modified_time: source_file_path_.empty ()" ), source_file_path_.empty () );
1571 islib::throw_if ( std::invalid_argument ( "keep_same_accessed_time_and_modified_time: destination_file_path_.empty ()" ), destination_file_path_.empty () );
1583 local_ ( source_file_path, destination_file_path );
1585 struct stat source_file_status_information;
1589 islib::stat_ ( source_file_path, &source_file_status_information );
1599 struct utimbuf utime_information;
1601 utime_information.actime = source_file_status_information.st_atime;
1602 utime_information.modtime = source_file_status_information.st_mtime;
1606 islib::utime_ ( destination_file_path, &utime_information );