1 /*
2  *      cook - file construction tool
3  *      Copyright (C) 2007 Peter Miller;
4  *      All rights reserved.
5  *
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation; either version 3 of the License, or
9  *      (at your option) any later version.
10  *
11  *      This program is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *      GNU General Public License for more details.
15  *
16  *      You should have received a copy of the GNU General Public License
17  *      along with this program. If not, see
18  *      <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <common/ac/errno.h>
22 #include <common/ac/unistd.h>
23 
24 #include <common/error_intl.h>
25 #include <cook/os_interface.h>
26 
27 
28 int
os_symlink(string_ty * from,string_ty * to,int echo)29 os_symlink(string_ty *from, string_ty *to, int echo)
30 {
31     int             err;
32 
33     err = symlink(from->str_text, to->str_text);
34     if (err)
35     {
36         char link_content[2000];
37 
38         if (errno != EEXIST)
39         {
40             sub_context_ty  *scp;
41 
42             whine:
43             scp = sub_context_new();
44             sub_var_set_string(scp, "File_Name_1", from);
45             sub_var_set_string(scp, "File_Name_2", to);
46             error_intl(scp, i18n("symlink($filename1, $filename2): $errno"));
47             sub_context_delete(scp);
48             return -1;
49         }
50         err = readlink(to->str_text, link_content, sizeof(link_content));
51         if (err < 0)
52         {
53             if (errno != EINVAL)
54             {
55                 sub_context_ty  *scp;
56 
57                 scp = sub_context_new();
58                 sub_var_set_string(scp, "File_Name", to);
59                 error_intl(scp, i18n("readlink \"$filename\": $errno"));
60                 sub_context_delete(scp);
61                 return -1;
62             }
63         }
64         else
65         {
66             string_ty       *s2;
67             int             ok;
68 
69             s2 = str_n_from_c(link_content, err);
70             ok = str_equal(s2, from);
71             str_free(s2);
72             if (ok)
73                 return 0;
74         }
75         err = unlink(to->str_text);
76         if (err < 0)
77         {
78             error_intl_unlink(to->str_text);
79             return -1;
80         }
81 
82         if (echo)
83         {
84             sub_context_ty  *scp;
85 
86             scp = sub_context_new();
87             sub_var_set_string(scp, "File_Name", to);
88             error_intl(scp, i18n("rm $filename"));
89             sub_context_delete(scp);
90         }
91 
92         err = symlink(from->str_text, to->str_text);
93         if (err < 0)
94             goto whine;
95     }
96     if (echo)
97     {
98         sub_context_ty  *scp;
99 
100         scp = sub_context_new();
101         sub_var_set_string(scp, "File_Name_1", from);
102         sub_var_set_string(scp, "File_Name_2", to);
103         error_intl(scp, i18n("ln -s $filename1 $filename2"));
104         sub_context_delete(scp);
105     }
106     return 0;
107 }
108