OSDN Git Service

Change symbolic links to regular files.
[alstede/alstede.git] / alstede.cpp
1 //
2 // Inclusion of standard header file
3 //
4 #include <algorithm>
5 #include <cctype>
6 #include <cerrno>
7 #include <cstddef>
8 #include <cstdlib>
9 #include <ctime>
10 #include <exception>
11 #include <limits>
12 #include <stdexcept>
13 #include <sstream>
14 #include <string>
15 #include <utility>
16 #include <vector>
17
18 //
19 // Inclusion of system header file
20 //
21 #include <sys/stat.h>
22 #include <getopt.h>
23 #include <unistd.h>
24
25 //
26 // Inclusion of library header file
27 //
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>
41
42 //
43 // Inclusion of configuration file
44 //
45 #ifdef HAVE_CONFIG_H
46 #  include "config.h"
47 #endif // HAVE_CONFIG_H
48
49 //
50 // Definition of type
51 //
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;
55
56 //
57 // Definition of file scope static constant
58 //
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 [] =
81   {
82     Delete_Option_Character,
83     Hour_Option_Character,
84     Minute_Option_Character,
85     Second_Option_Character,
86     Version_Option_Character,
87     Day_Option_Character,
88     Help_Option_Character,
89     Lexical_Option_Character,
90     ':',
91     Month_Option_Character,
92     Recursive_Option_Character,
93     Verbose_Option_Character,
94     Year_Option_Character,
95     0
96   };
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 [] =
110   {
111     {
112       Delete_Option_String,
113       no_argument,
114       0,
115       Hour_Option_Character
116     },
117     {
118       Hour_Option_String,
119       no_argument,
120       0,
121       Hour_Option_Character
122     },
123     {
124       Minute_Option_String,
125       no_argument,
126       0,
127       Minute_Option_Character
128     },
129     {
130       Second_Option_String,
131       no_argument,
132       0,
133       Second_Option_Character
134     },
135     {
136       Version_Option_String,
137       no_argument,
138       0,
139       Version_Option_Character
140     },
141     {
142       Day_Option_String,
143       no_argument,
144       0,
145       Day_Option_Character
146     },
147     {
148       Help_Option_String,
149       no_argument,
150       0,
151       Help_Option_Character
152     },
153     {
154       Lexical_Option_String,
155       required_argument,
156       0,
157       Lexical_Option_Character
158     },
159     {
160       Month_Option_String,
161       no_argument,
162       0,
163       Month_Option_Character
164     },
165     {
166       Recursive_Option_String,
167       no_argument,
168       0,
169       Recursive_Option_Character
170     },
171     {
172       Verbose_Option_String,
173       no_argument,
174       0,
175       Verbose_Option_Character
176     },
177     {
178       Year_Option_String,
179       no_argument,
180       0,
181       Year_Option_Character
182     },
183     {
184       0,
185       0,
186       0,
187       0
188     }
189   };
190 static char const Extension_Configuration_File_Name [] = ".alstede_extensions";
191 static char const Comment_Character = '#';
192
193 //
194 // Declaration of file scope static variable
195 //
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;
212
213 //
214 // Declaration of static function
215 //
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 & );
241
242 //
243 // Definition of main function
244 //
245 int
246 main
247   (
248     int const number_of_arguments,
249     char ** const argument_array
250   )
251 try
252   {
253     Home_Directory_Path = path_pointer_type ( new boost::filesystem::path ( std::getenv ( Home_Environment_Variable ) ) );
254
255     Extension_Configuration_File_Path = path_pointer_type ( new boost::filesystem::path ( get_extension_configuration_file_path () ) );
256
257     interpret_options ( number_of_arguments, argument_array );
258
259     read_extension_configuration_file ();
260
261     process_directory ( *Source_Directory_Path );
262
263     return EXIT_SUCCESS;
264   }
265 catch
266   (
267     islib::normal_termination const &normal_termination
268   )
269   {
270     return normal_termination.get_exit_status ();
271   }
272 catch
273   (
274     std::exception const &exception
275   )
276   {
277     islib::print_error_message ( std::string ( Program_Name ) + ": " + exception.what () );
278
279     return EXIT_FAILURE;
280   }
281 catch
282   (
283     islib::fatal_error const &fatal_error
284   )
285   {
286     char buffer [ BUFSIZ ];
287     char const *source = fatal_error.what ();
288     char *destination = buffer;
289
290     for ( ; *source; ++source, ++destination )
291       *destination = *source;
292
293     islib::write_assert ( STDERR_FILENO, buffer, BUFSIZ );
294
295     return EXIT_FAILURE;
296   }
297 catch
298   (
299     ...
300   )
301   {
302     islib::print_error_message ( std::string ( Program_Name ) + ": unexpected exception." );
303
304     return EXIT_FAILURE;
305   }
306
307 //
308 // Definition of static function
309 //
310 boost::filesystem::path
311 get_extension_configuration_file_path
312   (
313   )
314   {
315     boost::filesystem::path extension_configuration_file_path;
316
317     class local
318       {
319       public:
320         local
321           (
322             path_pointer_type const &home_directory_path,
323             boost::filesystem::path const &extension_configuration_file_path__
324           ):
325           extension_configuration_file_path_ ( extension_configuration_file_path__ )
326           {
327             islib::throw_if ( std::logic_error ( "get_extension_configuration_file_path: !home_directory_path" ), !home_directory_path );
328           }
329         
330         ~local
331           (
332           )
333           throw
334             (
335             )
336           {
337             islib::assert_ ( !this->extension_configuration_file_path_.empty (), "get_extension_configuration_file_path: `!this->extension_configuration_file_path_.empty ()' has failed." );
338           }
339
340       public:
341         boost::filesystem::path const &extension_configuration_file_path_;
342       }
343     local_ ( Home_Directory_Path, extension_configuration_file_path );
344
345     if ( !Home_Directory_Path->empty () )
346       extension_configuration_file_path = *Home_Directory_Path / Extension_Configuration_File_Name;
347     else
348       extension_configuration_file_path = boost::filesystem::path ( "." ) / Extension_Configuration_File_Name;
349
350     return extension_configuration_file_path;
351   }
352
353 //
354 // Definition of static function
355 //
356 void
357 interpret_options
358   (
359     int const number_of_arguments,
360     char ** const argument_array
361   )
362   {
363     class local
364       {
365       public:
366         local
367           (
368             int const number_of_arguments_,
369             char ** const argument_array_
370           )
371           {
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_ ) );
374           }
375         
376         ~local
377           (
378           )
379           throw
380             (
381             )
382           {
383           }
384       }
385     local_ ( number_of_arguments, argument_array );
386
387     while ( true )
388       {
389         int option_index = 0;
390
391         int const option_character = getopt_long ( number_of_arguments, argument_array, Option_String, Long_Option_Array, &option_index );
392
393         if ( option_character == -1 )
394           break;
395
396         switch ( option_character )
397           {
398           case Version_Option_Character:
399             print_version_message ();
400
401             throw islib::normal_termination ( EXIT_SUCCESS );
402
403           case Help_Option_Character:
404             print_help_message ();
405
406             throw islib::normal_termination ( EXIT_SUCCESS );
407
408           case Delete_Option_Character:
409             Delete_Mode_Flag = true;
410
411             break;
412
413           case Hour_Option_Character:
414             Hour_Mode_Flag = true;
415
416             break;
417
418           case Minute_Option_Character:
419             Minute_Mode_Flag = true;
420
421             break;
422
423           case Second_Option_Character:
424             Second_Mode_Flag = true;
425
426             break;
427
428           case Day_Option_Character:
429             Day_Mode_Flag = true;
430
431             break;
432
433           case Lexical_Option_Character:
434             Lexical_Mode_Flag = true;
435             Lexical_Depth = get_lexical_depth ( optarg );
436
437             break;
438
439           case Month_Option_Character:
440             Month_Mode_Flag = true;
441
442             break;
443
444           case Recursive_Option_Character:
445             Recursive_Mode_Flag = true;
446
447             break;
448
449           case Verbose_Option_Character:
450             Verbose_Mode_Flag = true;
451
452             break;
453
454           case Year_Option_Character:
455             Year_Mode_Flag = true;
456
457             break;
458
459           default:
460             islib::throw_ ( std::logic_error ( "interpret_options: unexpected option." ) );
461           }
462       }
463
464     check_flags ();
465
466     check_number_of_arguments ( number_of_arguments, argument_array, optind );
467
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" ) ) );
470
471     check_source_directory_path_and_destination_directory_path ();
472   }
473
474 //
475 // Definition of static function
476 //
477 void
478 read_extension_configuration_file
479   (
480   )
481   {
482     class local
483       {
484       public:
485         local
486           (
487             path_pointer_type const &extension_configuration_file_path
488           )
489           {
490             islib::throw_if ( std::logic_error ( "read_extension_configuration_file: !extension_configuration_file_path" ), !extension_configuration_file_path );
491           }
492         
493         ~local
494           (
495           )
496           throw
497             (
498             )
499           {
500           }
501       }
502     local_ ( Extension_Configuration_File_Path );
503
504     if ( !boost::filesystem::exists ( *Extension_Configuration_File_Path ) )
505       {
506         islib::print_error_message ( std::string ( Program_Name ) + ": extension configuration file `" + Extension_Configuration_File_Path->string () + "' does not exist." );
507
508         throw islib::normal_termination ( EXIT_FAILURE );
509       }
510
511     boost::filesystem::ifstream extension_configuration_file_stream ( *Extension_Configuration_File_Path );
512
513     if ( !extension_configuration_file_stream )
514       {
515         islib::print_error_message ( std::string ( Program_Name ) + ": opening extension configuration file `" + Extension_Configuration_File_Path->string () + "' has failed." );
516
517         throw islib::normal_termination ( EXIT_FAILURE );
518       }
519
520     std::string line;
521
522     Extension_Vector = string_vector_pointer_type ( new string_vector_type () );
523
524     while ( std::getline ( extension_configuration_file_stream, line ) )
525       {
526         std::string const extension ( islib::trim ( line ) );
527
528         if ( extension.empty () || extension [ 0 ] == Comment_Character )
529           continue;
530
531         if ( Verbose_Mode_Flag )
532           islib::print_message ( std::string ( Program_Name ) + ": extension `" + extension + "' has been included." );
533
534         Extension_Vector->push_back ( extension );
535       }
536   }
537
538 //
539 // Definition of static function
540 //
541 void
542 process_directory
543   (
544     boost::filesystem::path const &directory_path
545   )
546   {
547     class local
548       {
549       public:
550         local
551           (
552             boost::filesystem::path const &directory_path_
553           )
554           {
555             islib::throw_if ( std::invalid_argument ( "process_directory: directory_path_.empty ()" ), directory_path_.empty () );
556           }
557         
558         ~local
559           (
560           )
561           throw
562             (
563             )
564           {
565           }
566       }
567     local_ ( directory_path );
568
569     for ( boost::filesystem::directory_iterator directory_iterator ( directory_path ); directory_iterator != boost::filesystem::directory_iterator (); ++directory_iterator )
570       {
571         boost::filesystem::path const &path ( *directory_iterator );
572
573         if ( path.leaf () [ 0 ] == '.' )
574           continue;
575
576         if ( boost::filesystem::is_directory ( path ) )
577           {
578             if ( Recursive_Mode_Flag )
579               process_directory ( path );
580           }
581         else
582           process_file ( path );
583       }
584   }
585
586 //
587 // Definition of static function
588 //
589 void
590 print_version_message
591   (
592   )
593   {
594     std::stringstream version_message_stream;
595
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"
602       << "\n"
603       << "Written by " << Writer_Name << "\n";
604
605     islib::print_message ( version_message_stream.str () );
606   }
607
608 //
609 // Definition of static function
610 //
611 void
612 print_help_message
613   (
614   )
615   {
616     std::stringstream help_message_stream;
617
618     help_message_stream
619       << "Usage: " << Program_Name << " [option] source-directory destination-directory\n"
620       << "\n"
621       << "Link or copy files from source-directory to destination-directory.\n"
622       << "\n"
623       << "Options:\n"
624       << "\n"
625       << "  -" << Delete_Option_Character << ", --" << Delete_Option_String << "\n"
626       << "\n"
627       << "          delete source file.\n"
628       << "\n"
629       << "\n"
630       << "  -" << Hour_Option_Character << ", --" << Hour_Option_String << "\n"
631       << "\n"
632       << "          create hour directories. need to specify -" << Day_Option_Character << " or --" << Day_Option_String << ".\n"
633       << "\n"
634       << "\n"
635       << "  -" << Minute_Option_Character << ", --" << Minute_Option_String << "\n"
636       << "\n"
637       << "          create minute directories. need to specify -" << Hour_Option_Character << " or --" << Hour_Option_String << ".\n"
638       << "\n"
639       << "\n"
640       << "  -" << Second_Option_Character << ", --" << Second_Option_String << "\n"
641       << "\n"
642       << "          create second directories. need to specify -" << Minute_Option_Character << " or --" << Minute_Option_String << ".\n"
643       << "\n"
644       << "\n"
645       << "  -" << Version_Option_Character << ", --" << Version_Option_String << "\n"
646       << "\n"
647       << "          print version message and exit.\n"
648       << "\n"
649       << "\n"
650       << "  -" << Day_Option_Character << ", --" << Day_Option_String << "\n"
651       << "\n"
652       << "          create day directories. need to specify -" << Month_Option_Character << " or --" << Month_Option_String << ".\n"
653       << "\n"
654       << "\n"
655       << "  -" << Help_Option_Character << ", --" << Help_Option_String << "\n"
656       << "\n"
657       << "          print this help message and exit.\n"
658       << "\n"
659       << "\n"
660       << "  -" << Lexical_Option_Character << " N, --" << Lexical_Option_String << " N\n"
661       << "\n"
662       << "          create lexical directories. N is lexical depth.\n"
663       << "\n"
664       << "\n"
665       << "  -" << Month_Option_Character << ", --" << Month_Option_String << "\n"
666       << "\n"
667       << "          create month directories. need to specify -" << Year_Option_Character << " or --" << Year_Option_String << ".\n"
668       << "\n"
669       << "\n"
670       << "  -" << Recursive_Option_Character << ", --" << Recursive_Option_String << "\n"
671       << "\n"
672       << "          do it at a directory below source-directory recursively.\n"
673       << "\n"
674       << "\n"
675       << "  -" << Verbose_Option_Character << ", --" << Verbose_Option_String << "\n"
676       << "\n"
677       << "          explain what is being done.\n"
678       << "\n"
679       << "\n"
680       << "  -" << Year_Option_Character << ", --" << Year_Option_String << "\n"
681       << "\n"
682       << "          create year directories.\n"
683       << "\n";
684
685     islib::print_message ( help_message_stream.str () );
686   }
687
688 //
689 // Definition of static function
690 //
691 std::size_t
692 get_lexical_depth
693   (
694     char * const lexical_depth_string
695   )
696   {
697     class local
698       {
699       public:
700         local
701           (
702             char * const lexical_depth_string_
703           )
704           {
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_ );
707           }
708         
709         ~local
710           (
711           )
712           throw
713             (
714             )
715           {
716           }
717       }
718     local_ ( lexical_depth_string );
719
720     std::size_t lexical_depth = 0;
721
722     try
723       {
724         lexical_depth = boost::lexical_cast < std::size_t > ( lexical_depth_string );
725       }
726     catch ( boost::bad_lexical_cast const &bad_lexical_cast )
727       {
728         std::stringstream error_message_stream;
729
730         error_message_stream
731           << Program_Name << ": invalid lexical depth.\n"
732           << islib::get_try_help_message ( Program_Name );
733
734         islib::print_error_message ( error_message_stream.str () );
735
736         throw islib::normal_termination ( EXIT_FAILURE );
737       }
738
739     if ( lexical_depth == 0 )
740       {
741         std::stringstream error_message_stream;
742
743         error_message_stream
744           << Program_Name << ": lexical depth is 0.\n"
745           << islib::get_try_help_message ( Program_Name );
746
747         islib::print_error_message ( error_message_stream.str () );
748
749         throw islib::normal_termination ( EXIT_FAILURE );
750       }
751
752     return lexical_depth;
753   }
754
755 //
756 // Definition of static function
757 //
758 void
759 check_flags
760   (
761   )
762   {
763     if ( !Year_Mode_Flag && Month_Mode_Flag )
764       {
765         std::stringstream error_message_stream;
766
767         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 );
770
771         islib::print_error_message ( error_message_stream.str () );
772
773         throw islib::normal_termination ( EXIT_FAILURE );
774       }
775
776     if ( !Month_Mode_Flag && Day_Mode_Flag )
777       {
778         std::stringstream error_message_stream;
779
780         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 );
783
784         islib::print_error_message ( error_message_stream.str () );
785
786         throw islib::normal_termination ( EXIT_FAILURE );
787       }
788
789     if ( !Day_Mode_Flag && Hour_Mode_Flag )
790       {
791         std::stringstream error_message_stream;
792
793         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 );
796
797         islib::print_error_message ( error_message_stream.str () );
798
799         throw islib::normal_termination ( EXIT_FAILURE );
800       }
801
802     if ( !Hour_Mode_Flag && Minute_Mode_Flag )
803       {
804         std::stringstream error_message_stream;
805
806         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 );
809
810         islib::print_error_message ( error_message_stream.str () );
811
812         throw islib::normal_termination ( EXIT_FAILURE );
813       }
814
815     if ( !Minute_Mode_Flag && Second_Mode_Flag )
816       {
817         std::stringstream error_message_stream;
818
819         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 );
822
823         islib::print_error_message ( error_message_stream.str () );
824
825         throw islib::normal_termination ( EXIT_FAILURE );
826       }
827   }
828
829 //
830 // Definition of static function
831 //
832 void
833 check_number_of_arguments
834   (
835     int const number_of_arguments,
836     char ** const argument_array,
837     int const option_index
838   )
839   {
840     class local
841       {
842       public:
843         local
844           (
845             int const number_of_arguments_,
846             char ** const argument_array_,
847             int const option_index_
848           )
849           {
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 );
853           }
854         
855         ~local
856           (
857           )
858           throw
859             (
860             )
861           {
862           }
863       }
864     local_ ( number_of_arguments, argument_array, option_index );
865
866     if ( option_index + Number_Of_Static_Arguments < number_of_arguments )
867       {
868         std::stringstream error_message_stream;
869
870         error_message_stream << Program_Name << ( number_of_arguments - ( option_index + Number_Of_Static_Arguments ) == 1? ": unknown argument: `": ": unknown arguments: `" );
871
872         for ( int index_of_argument = option_index + Number_Of_Static_Arguments; index_of_argument != number_of_arguments; ++index_of_argument )
873           {
874             if ( index_of_argument != option_index + Number_Of_Static_Arguments )
875               error_message_stream << " ";
876
877             error_message_stream << argument_array [ index_of_argument ];
878           }
879
880         error_message_stream
881           << "'.\n"
882           << islib::get_try_help_message ( Program_Name );
883
884         islib::print_error_message ( error_message_stream.str () );
885
886         throw islib::normal_termination ( EXIT_FAILURE );
887       }
888     else if ( option_index == number_of_arguments )
889       {
890         std::stringstream error_message_stream;
891
892         error_message_stream
893           << Program_Name << ": source directory and destination directory are not specified.\n"
894           << islib::get_try_help_message ( Program_Name );
895
896         islib::print_error_message ( error_message_stream.str () );
897
898         throw islib::normal_termination ( EXIT_FAILURE );
899       }
900     else if ( option_index == number_of_arguments - 1 )
901       {
902         std::stringstream error_message_stream;
903
904         error_message_stream
905           << Program_Name << ": destination directory is not specified.\n"
906           << islib::get_try_help_message ( Program_Name );
907
908         islib::print_error_message ( error_message_stream.str () );
909
910         throw islib::normal_termination ( EXIT_FAILURE );
911       }
912   }
913
914 //
915 // Definition of static function
916 //
917 boost::filesystem::path
918 get_directory_path
919   (
920     char * const directory_path_string,
921     std::string const &kind_name_of_directory
922   )
923   {
924     boost::filesystem::path directory_path;
925
926     class local
927       {
928       public:
929         local
930           (
931             char * const directory_path_string_,
932             std::string const &kind_name_of_directory_,
933             boost::filesystem::path const &directory_path__
934           ):
935           directory_path_ ( directory_path__ )
936           {
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 () );
940           }
941         
942         ~local
943           (
944           )
945           throw
946             (
947             )
948           {
949             islib::assert_ ( !this->directory_path_.empty (), "get_directory_path: `!this->directory_path_.empty ()' has failed." );
950           }
951
952       private:
953         boost::filesystem::path const &directory_path_;
954       }
955     local_ ( directory_path_string, kind_name_of_directory, directory_path );
956
957     directory_path = directory_path_string;
958
959     if ( !boost::filesystem::exists ( directory_path ) )
960       {
961         islib::print_error_message ( std::string ( Program_Name ) + ": " + kind_name_of_directory + " directory `" + directory_path.string () + "' does not exist." );
962
963         throw islib::normal_termination ( EXIT_FAILURE );
964       }
965
966     if ( !boost::filesystem::is_directory ( directory_path ) )
967       {
968         std::stringstream error_message_stream;
969
970         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 );
973
974         islib::print_error_message ( error_message_stream.str () );
975
976         throw islib::normal_termination ( EXIT_FAILURE );
977       }
978
979     return directory_path;
980   }
981
982 //
983 // Definition of static function
984 //
985 void
986 check_source_directory_path_and_destination_directory_path
987   (
988   )
989   {
990     class local
991       {
992       public:
993         local
994           (
995             path_pointer_type const &source_directory_path,
996             path_pointer_type const &destination_directory_path
997           )
998           {
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 );
1001           }
1002         
1003         ~local
1004           (
1005           )
1006           throw
1007             (
1008             )
1009           {
1010           }
1011       }
1012     local_ ( Source_Directory_Path, Destination_Directory_Path );
1013
1014     if ( *Source_Directory_Path == *Destination_Directory_Path )
1015       {
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." );
1017
1018         throw islib::normal_termination ( EXIT_FAILURE );
1019       }
1020
1021     struct stat source_directory_status;
1022     struct stat destination_directory_status;
1023
1024     try
1025       {
1026         islib::stat_ ( *Source_Directory_Path, &source_directory_status );
1027       }
1028     catch
1029       (
1030         ...
1031       )
1032       {
1033         islib::print_error_message ( std::string ( Program_Name ) + ": getting directory `" + Source_Directory_Path->string () + "''s status has failed." );
1034
1035         throw islib::normal_termination ( EXIT_FAILURE );
1036       }
1037
1038     try
1039       {
1040         islib::stat_ ( *Destination_Directory_Path, &destination_directory_status );
1041       }
1042     catch
1043       (
1044         ...
1045       )
1046       {
1047         islib::print_error_message ( std::string ( Program_Name ) + ": getting directory `" + Destination_Directory_Path->string () + "''s status has failed." );
1048
1049         throw islib::normal_termination ( EXIT_FAILURE );
1050       }
1051
1052     if ( source_directory_status.st_dev == destination_directory_status.st_dev && source_directory_status.st_ino == destination_directory_status.st_ino )
1053       {
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." );
1055
1056         throw islib::normal_termination ( EXIT_FAILURE );
1057       }
1058   }
1059
1060 //
1061 // Definition of static function
1062 //
1063 void
1064 process_file
1065   (
1066     boost::filesystem::path const &file_path
1067   )
1068   {
1069     class local
1070       {
1071       public:
1072         local
1073           (
1074             boost::filesystem::path const &file_path_
1075           )
1076           {
1077             islib::throw_if ( std::invalid_argument ( "process_file: file_path_.empty ()" ), file_path_.empty () );
1078           }
1079         
1080         ~local
1081           (
1082           )
1083           throw
1084             (
1085             )
1086           {
1087           }
1088       }
1089     local_ ( file_path );
1090
1091     std::string const file_name ( file_path.leaf () );
1092
1093     if ( file_name.find ( '.' ) != std::string::npos && std::find ( Extension_Vector->begin (), Extension_Vector->end (), boost::filesystem::extension ( file_path ) ) != Extension_Vector->end () )
1094       {
1095         if ( Year_Mode_Flag || Lexical_Mode_Flag )
1096           {
1097             if ( Year_Mode_Flag )
1098               process_year_mode ( file_path );
1099
1100             if ( Lexical_Mode_Flag )
1101               process_lexical_mode ( file_path );
1102           }
1103         else
1104           link_or_copy_file ( file_path, *Destination_Directory_Path / file_name );
1105       }
1106
1107     if ( Delete_Mode_Flag )
1108       unlink_file ( file_path );
1109   }
1110
1111 //
1112 // Definition of static function
1113 //
1114 bool
1115 is_valid_argument_array
1116   (
1117     char ** const argument_array,
1118     int const number_of_arguments
1119   )
1120   {
1121     if ( !argument_array )
1122       return false;
1123
1124     for ( int index_of_argument = 0; index_of_argument != number_of_arguments; ++index_of_argument )
1125       if ( !argument_array [ index_of_argument ] )
1126         return false;
1127
1128     return true;
1129   }
1130
1131 //
1132 // Definition of static function
1133 //
1134 void
1135 process_year_mode
1136   (
1137     boost::filesystem::path const &source_file_path
1138   )
1139   {
1140     class local
1141       {
1142       public:
1143         local
1144           (
1145             boost::filesystem::path const &source_file_path_
1146           )
1147           {
1148             islib::throw_if ( std::invalid_argument ( "process_year_mode: source_file_path_.empty ()" ), source_file_path_.empty () );
1149           }
1150         
1151         ~local
1152           (
1153           )
1154           throw
1155             (
1156             )
1157           {
1158           }
1159       }
1160     local_ ( source_file_path );
1161
1162     boost::filesystem::path destination_directory_path ( *Destination_Directory_Path );
1163     struct stat source_file_status_information;
1164
1165     try
1166       {
1167         islib::stat_ ( source_file_path, &source_file_status_information );
1168       }
1169     catch
1170       (
1171         ...
1172       )
1173       {
1174         islib::print_error_message ( std::string ( Program_Name ) + ": getting file `" + source_file_path.string () + "''s status has failed." );
1175
1176         throw islib::normal_termination ( EXIT_FAILURE );
1177       }
1178
1179     tzset ();
1180
1181     struct tm source_file_modified_time_information;
1182
1183     try
1184       {
1185         islib::localtime_r_ ( &source_file_status_information.st_mtime, &source_file_modified_time_information );
1186       }
1187     catch
1188       (
1189         ...
1190       )
1191       {
1192         islib::print_error_message ( std::string ( Program_Name ) + ": converting time has failed." );
1193
1194         throw islib::normal_termination ( EXIT_FAILURE );
1195       }
1196
1197     destination_directory_path /= boost::lexical_cast < std::string > ( source_file_modified_time_information.tm_year + 1900 );
1198
1199     if ( !boost::filesystem::exists ( destination_directory_path ) )
1200       create_directory ( destination_directory_path, "year" );
1201
1202     if ( Month_Mode_Flag )
1203       process_month_mode ( destination_directory_path, source_file_modified_time_information );
1204
1205     std::string const destination_file_name ( get_destination_file_name ( source_file_path, destination_directory_path ) );
1206
1207     if ( !destination_file_name.empty () )
1208       link_or_copy_file ( source_file_path, destination_directory_path / destination_file_name );
1209   }
1210
1211 //
1212 // Definition of static function
1213 //
1214 void
1215 process_lexical_mode
1216   (
1217     boost::filesystem::path const &source_file_path
1218   )
1219   {
1220     class local
1221       {
1222       public:
1223         local
1224           (
1225             boost::filesystem::path const &source_file_path_
1226           )
1227           {
1228             islib::throw_if ( std::invalid_argument ( "process_lexical_mode: source_file_path_.empty ()" ), source_file_path_.empty () );
1229           }
1230         
1231         ~local
1232           (
1233           )
1234           throw
1235             (
1236             )
1237           {
1238           }
1239       }
1240     local_ ( source_file_path );
1241    
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 () );
1245
1246     for ( std::size_t index_of_file_basename = 0; index_of_file_basename != lexical_depth; ++index_of_file_basename )
1247       {
1248         if ( !std::isgraph ( file_basename [ index_of_file_basename ] ) || file_basename [ index_of_file_basename ] == '.' )
1249           break;
1250
1251         destination_directory_path /= std::string ( 1, file_basename [ index_of_file_basename ] );
1252
1253         if ( !boost::filesystem::exists ( destination_directory_path ) )
1254           create_directory ( destination_directory_path, "lexical" );
1255       }
1256
1257     std::string const destination_file_name ( get_destination_file_name ( source_file_path, destination_directory_path ) );
1258
1259     if ( !destination_file_name.empty () )
1260       link_or_copy_file ( source_file_path, destination_directory_path / destination_file_name );
1261   }
1262
1263 //
1264 // Definition of static function
1265 //
1266 void
1267 unlink_file
1268   (
1269     boost::filesystem::path const &file_path
1270   )
1271   {
1272     class local
1273       {
1274       public:
1275         local
1276           (
1277             boost::filesystem::path const &file_path_
1278           )
1279           {
1280             islib::throw_if ( std::invalid_argument ( "unlink_file: file_path_.empty ()" ), file_path_.empty () );
1281           }
1282         
1283         ~local
1284           (
1285           )
1286           throw
1287             (
1288             )
1289           {
1290           }
1291       }
1292     local_ ( file_path );
1293
1294     try
1295       {
1296         islib::unlink_ ( file_path );
1297       }
1298     catch
1299       (
1300         ...
1301       )
1302       {
1303         islib::print_error_message ( std::string ( Program_Name ) + ": unlinking file `" + file_path.string () + "' has failed." );
1304
1305         throw islib::normal_termination ( EXIT_FAILURE );
1306       }
1307
1308     if ( Verbose_Mode_Flag )
1309       islib::print_message ( std::string ( Program_Name ) + ": file `" + file_path.string () + "' has been unlinked." );
1310   }
1311
1312 //
1313 // Definition of static function
1314 //
1315 // Return value: std::string (): there is identical file in destination_directory_path.
1316 //
1317 std::string
1318 get_destination_file_name
1319   (
1320     boost::filesystem::path const &source_file_path,
1321     boost::filesystem::path const &destination_directory_path
1322   )
1323   {
1324     class local
1325       {
1326       public:
1327         local
1328           (
1329             boost::filesystem::path const &source_file_path_,
1330             boost::filesystem::path const &destination_directory_path_
1331           )
1332           {
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 () );
1335           }
1336         
1337         ~local
1338           (
1339           )
1340           throw
1341             (
1342             )
1343           {
1344           }
1345       }
1346     local_ ( source_file_path, destination_directory_path );
1347
1348     std::string destination_file_name;
1349     std::size_t repetition_number = 0;
1350
1351     destination_file_name = source_file_path.leaf ();
1352
1353     while ( boost::filesystem::exists ( destination_directory_path / destination_file_name ) )
1354       {
1355         if ( islib::binary_compare ( source_file_path, destination_directory_path / destination_file_name ) == 0 )
1356           return std::string ();
1357
1358         if ( repetition_number == std::numeric_limits < std::size_t >::max () )
1359           {
1360             islib::print_error_message ( std::string ( Program_Name ) + ": repetition number of file `" + source_file_path.string () + "' has overflowen." );
1361
1362             throw islib::normal_termination ( EXIT_FAILURE );
1363           }
1364
1365         ++repetition_number;
1366
1367         destination_file_name = boost::filesystem::basename ( source_file_path ) + " (" + boost::lexical_cast < std::string > ( repetition_number ) + ")" + boost::filesystem::extension ( source_file_path );
1368       }
1369
1370     return destination_file_name;
1371   }
1372
1373 //
1374 // Definition of static function
1375 //
1376 void
1377 process_month_mode
1378   (
1379     boost::filesystem::path &destination_directory_path,
1380     struct tm const &source_file_modified_time_information
1381   )
1382   {
1383     class local
1384       {
1385       public:
1386         local
1387           (
1388             boost::filesystem::path const &destination_directory_path_
1389           )
1390           {
1391             islib::throw_if ( std::invalid_argument ( "process_month_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1392           }
1393         
1394         ~local
1395           (
1396           )
1397           throw
1398             (
1399             )
1400           {
1401           }
1402       }
1403     local_ ( destination_directory_path );
1404
1405     destination_directory_path /= ( boost::format ( "%02d" ) % ( source_file_modified_time_information.tm_mon + 1 ) ).str ();
1406
1407     if ( !boost::filesystem::exists ( destination_directory_path ) )
1408       create_directory ( destination_directory_path, "month" );
1409
1410     if ( Day_Mode_Flag )
1411       process_day_mode ( destination_directory_path, source_file_modified_time_information );
1412   }
1413
1414 //
1415 // Definition of static function
1416 //
1417 void
1418 process_day_mode
1419   (
1420     boost::filesystem::path &destination_directory_path,
1421     struct tm const &source_file_modified_time_information
1422   )
1423   {
1424     class local
1425       {
1426       public:
1427         local
1428           (
1429             boost::filesystem::path const &destination_directory_path_
1430           )
1431           {
1432             islib::throw_if ( std::invalid_argument ( "process_day_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1433           }
1434         
1435         ~local
1436           (
1437           )
1438           throw
1439             (
1440             )
1441           {
1442           }
1443       }
1444     local_ ( destination_directory_path );
1445
1446     destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_mday ).str ();
1447
1448     if ( !boost::filesystem::exists ( destination_directory_path ) )
1449       create_directory ( destination_directory_path, "day" );
1450
1451     if ( Hour_Mode_Flag )
1452       process_hour_mode ( destination_directory_path, source_file_modified_time_information );
1453   }
1454
1455 //
1456 // Definition of static function
1457 //
1458 void
1459 process_hour_mode
1460   (
1461     boost::filesystem::path &destination_directory_path,
1462     struct tm const &source_file_modified_time_information
1463   )
1464   {
1465     class local
1466       {
1467       public:
1468         local
1469           (
1470             boost::filesystem::path const &destination_directory_path_
1471           )
1472           {
1473             islib::throw_if ( std::invalid_argument ( "process_hour_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1474           }
1475         
1476         ~local
1477           (
1478           )
1479           throw
1480             (
1481             )
1482           {
1483           }
1484       }
1485     local_ ( destination_directory_path );
1486
1487     destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_hour ).str ();
1488
1489     if ( !boost::filesystem::exists ( destination_directory_path ) )
1490       create_directory ( destination_directory_path, "hour" );
1491
1492     if ( Minute_Mode_Flag )
1493       process_minute_mode ( destination_directory_path, source_file_modified_time_information );
1494   }
1495
1496 //
1497 // Definition of static function
1498 //
1499 void
1500 process_minute_mode
1501   (
1502     boost::filesystem::path &destination_directory_path,
1503     struct tm const &source_file_modified_time_information
1504   )
1505   {
1506     class local
1507       {
1508       public:
1509         local
1510           (
1511             boost::filesystem::path const &destination_directory_path_
1512           )
1513           {
1514             islib::throw_if ( std::invalid_argument ( "process_minute_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1515           }
1516         
1517         ~local
1518           (
1519           )
1520           throw
1521             (
1522             )
1523           {
1524           }
1525       }
1526     local_ ( destination_directory_path );
1527
1528     destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_min ).str ();
1529
1530     if ( !boost::filesystem::exists ( destination_directory_path ) )
1531       create_directory ( destination_directory_path, "minute" );
1532
1533     if ( Second_Mode_Flag )
1534       process_second_mode ( destination_directory_path, source_file_modified_time_information );
1535   }
1536
1537 //
1538 // Definition of static function
1539 //
1540 void
1541 process_second_mode
1542   (
1543     boost::filesystem::path &destination_directory_path,
1544     struct tm const &source_file_modified_time_information
1545   )
1546   {
1547     class local
1548       {
1549       public:
1550         local
1551           (
1552             boost::filesystem::path const &destination_directory_path_
1553           )
1554           {
1555             islib::throw_if ( std::invalid_argument ( "process_second_mode: destination_directory_path_.empty ()" ), destination_directory_path_.empty () );
1556           }
1557         
1558         ~local
1559           (
1560           )
1561           throw
1562             (
1563             )
1564           {
1565           }
1566       }
1567     local_ ( destination_directory_path );
1568
1569     destination_directory_path /= ( boost::format ( "%02d" ) % source_file_modified_time_information.tm_sec ).str ();
1570
1571     if ( !boost::filesystem::exists ( destination_directory_path ) )
1572       create_directory ( destination_directory_path, "second" );
1573   }
1574
1575 //
1576 // Definition of static function
1577 //
1578 void
1579 create_directory
1580   (
1581     boost::filesystem::path const &directory_path,
1582     std::string const &kind_name_of_directory
1583   )
1584   {
1585     class local
1586       {
1587       public:
1588         local
1589           (
1590             boost::filesystem::path const &directory_path_,
1591             std::string const &kind_name_of_directory_
1592           )
1593           {
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 () );
1596           }
1597         
1598         ~local
1599           (
1600           )
1601           throw
1602             (
1603             )
1604           {
1605           }
1606       }
1607     local_ ( directory_path, kind_name_of_directory );
1608
1609     try
1610       {
1611         islib::mkdir_ ( directory_path, 0755 );
1612       }
1613     catch
1614       (
1615         ...
1616       )
1617       {
1618         islib::print_error_message ( std::string ( Program_Name ) + ": creating directory `" + directory_path.string () + "' has failed." );
1619
1620         throw islib::normal_termination ( EXIT_FAILURE );
1621       }
1622
1623     if ( Verbose_Mode_Flag )
1624       islib::print_message ( std::string ( Program_Name ) + ": " + kind_name_of_directory + " directory `" + directory_path.string () + "' has been created." );
1625   }
1626
1627 //
1628 // Definition of static function
1629 //
1630 void
1631 link_or_copy_file
1632   (
1633     boost::filesystem::path const &source_file_path,
1634     boost::filesystem::path const &destination_file_path
1635   )
1636   {
1637     class local
1638       {
1639       public:
1640         local
1641           (
1642             boost::filesystem::path const &source_file_path_,
1643             boost::filesystem::path const &destination_file_path_
1644           )
1645           {
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 () );
1648           }
1649         
1650         ~local
1651           (
1652           )
1653           throw
1654             (
1655             )
1656           {
1657           }
1658       }
1659     local_ ( source_file_path, destination_file_path );
1660
1661     int link_return_value = link ( source_file_path.string ().c_str (), destination_file_path.string ().c_str () );
1662
1663     if ( link_return_value != 0 )
1664       {
1665         int const saved_errno = errno;
1666
1667         if ( saved_errno == EPERM || saved_errno == EXDEV )
1668           {
1669             try
1670               {
1671                 boost::filesystem::copy_file ( source_file_path, destination_file_path );
1672               }
1673             catch
1674               (
1675                 ...
1676               )
1677               {
1678                 islib::print_error_message ( std::string ( Program_Name ) + ": copying file `" + source_file_path.string () + "' to `" + destination_file_path.string () + "' has failed." );
1679
1680                 throw islib::normal_termination ( EXIT_FAILURE );
1681               }
1682
1683             keep_same_accessed_time_and_modified_time ( source_file_path, destination_file_path );
1684
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 () + "'." );
1687
1688             return;
1689           }
1690         else
1691           {
1692             islib::print_error_message ( std::string ( Program_Name ) + ": linking file `" + source_file_path.string () + "' to `" + destination_file_path.string () + "' has failed." );
1693
1694             throw islib::normal_termination ( EXIT_FAILURE );
1695           }
1696       }
1697
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 () + "'." );
1700   }
1701
1702 //
1703 // Definition of static function
1704 //
1705 void
1706 keep_same_accessed_time_and_modified_time
1707   (
1708     boost::filesystem::path const &source_file_path,
1709     boost::filesystem::path const &destination_file_path
1710   )
1711   {
1712     class local
1713       {
1714       public:
1715         local
1716           (
1717             boost::filesystem::path const &source_file_path_,
1718             boost::filesystem::path const &destination_file_path_
1719           )
1720           {
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 () );
1723           }
1724         
1725         ~local
1726           (
1727           )
1728           throw
1729             (
1730             )
1731           {
1732           }
1733       }
1734     local_ ( source_file_path, destination_file_path );
1735
1736     struct stat source_file_status_information;
1737
1738     try
1739       {
1740         islib::stat_ ( source_file_path, &source_file_status_information );
1741       }
1742     catch
1743       (
1744         ...
1745       )
1746       {
1747         islib::print_error_message ( std::string ( Program_Name ) + ": getting file `" + source_file_path.string () + "''s status has failed." );
1748
1749         throw islib::normal_termination ( EXIT_FAILURE );
1750       }
1751
1752     struct utimbuf utime_information;
1753
1754     utime_information.actime = source_file_status_information.st_atime;
1755     utime_information.modtime = source_file_status_information.st_mtime;
1756
1757     try
1758       {
1759         islib::utime_ ( destination_file_path, &utime_information );
1760       }
1761     catch
1762       (
1763         ...
1764       )
1765       {
1766         islib::print_error_message ( std::string ( Program_Name ) + ": setting file `" + source_file_path.string () + "''s accessed time and modified time has failed." );
1767
1768         throw islib::normal_termination ( EXIT_FAILURE );
1769       }
1770   }
1771
1772 //
1773 // End of file
1774 //