]> git.ipfire.org Git - thirdparty/glibc.git/blame - elf/sln.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / elf / sln.c
CommitLineData
ba9fcb3f 1/* `sln' program to create symbolic links between files.
2b778ceb 2 Copyright (C) 1998-2021 Free Software Foundation, Inc.
9d141cae
UD
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9d141cae
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
9d141cae 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
cbbcaf23 18
ba9fcb3f
UD
19#include <error.h>
20#include <errno.h>
cbbcaf23
UD
21#include <libintl.h>
22#include <locale.h>
9d141cae
UD
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <unistd.h>
26#include <errno.h>
27#include <ctype.h>
28#include <stdio.h>
29#include <string.h>
30#include <limits.h>
31
cbbcaf23
UD
32#include "../version.h"
33
34#define PACKAGE _libc_intl_domainname
35
d8cf93f4
UD
36static int makesymlink (const char *src, const char *dest);
37static int makesymlinks (const char *file);
cbbcaf23 38static void usage (void);
9d141cae
UD
39
40int
df777c40 41main (int argc, char **argv)
9d141cae 42{
cbbcaf23
UD
43 /* Set locale via LC_ALL. */
44 setlocale (LC_ALL, "");
45
46 /* Set the text message domain. */
47 textdomain (PACKAGE);
48
9d141cae
UD
49 switch (argc)
50 {
51 case 2:
cbbcaf23 52 if (strcmp (argv[1], "--version") == 0) {
8b748aed 53 printf ("sln %s%s\n", PKGVERSION, VERSION);
cbbcaf23
UD
54 return 0;
55 } else if (strcmp (argv[1], "--help") == 0) {
56 usage ();
57 return 0;
58 }
ba9fcb3f 59 return makesymlinks (argv [1]);
9d141cae
UD
60 break;
61
62 case 3:
ba9fcb3f 63 return makesymlink (argv [1], argv [2]);
9d141cae
UD
64 break;
65
66 default:
cbbcaf23 67 usage ();
9d141cae
UD
68 return 1;
69 break;
70 }
71}
72
cbbcaf23
UD
73static void
74usage (void)
75{
76 printf (_("Usage: sln src dest|file\n\n"));
8b748aed
JM
77 printf (_("For bug reporting instructions, please see:\n\
78%s.\n"), REPORT_BUGS_TO);
cbbcaf23
UD
79}
80
9d141cae 81static int
9d46370c 82makesymlinks (const char *file)
9d141cae 83{
ba9fcb3f
UD
84 char *buffer = NULL;
85 size_t bufferlen = 0;
86 int ret;
9d141cae 87 int lineno;
9d141cae
UD
88 FILE *fp;
89
ba9fcb3f
UD
90 if (strcmp (file, "-") == 0)
91 fp = stdin;
92 else
9d141cae 93 {
ba9fcb3f
UD
94 fp = fopen (file, "r");
95 if (fp == NULL)
96 {
cbbcaf23 97 fprintf (stderr, _("%s: file open error: %m\n"), file);
ba9fcb3f
UD
98 return 1;
99 }
9d141cae
UD
100 }
101
102 ret = 0;
103 lineno = 0;
ba9fcb3f 104 while (!feof_unlocked (fp))
9d141cae 105 {
ba9fcb3f
UD
106 ssize_t n = getline (&buffer, &bufferlen, fp);
107 char *src;
108 char *dest;
109 char *cp = buffer;
110
111 if (n < 0)
112 break;
113 if (buffer[n - 1] == '\n')
114 buffer[n - 1] = '\0';
115
116 ++lineno;
117 while (isspace (*cp))
118 ++cp;
119 if (*cp == '\0')
120 /* Ignore empty lines. */
121 continue;
122 src = cp;
123
124 do
125 ++cp;
126 while (*cp != '\0' && ! isspace (*cp));
127 if (*cp != '\0')
128 *cp++ = '\0';
129
130 while (isspace (*cp))
131 ++cp;
132 if (*cp == '\0')
9d141cae 133 {
cbbcaf23 134 fprintf (stderr, _("No target in line %d\n"), lineno);
ba9fcb3f 135 ret = 1;
9d141cae
UD
136 continue;
137 }
ba9fcb3f 138 dest = cp;
9d141cae 139
ba9fcb3f
UD
140 do
141 ++cp;
142 while (*cp != '\0' && ! isspace (*cp));
143 if (*cp != '\0')
144 *cp++ = '\0';
145
146 ret |= makesymlink (src, dest);
9d141cae
UD
147 }
148 fclose (fp);
149
150 return ret;
151}
152
153static int
9d46370c 154makesymlink (const char *src, const char *dest)
9d141cae 155{
f5e753c8 156 struct stat64 stats;
9d141cae
UD
157 const char *error;
158
159 /* Destination must not be a directory. */
f5e753c8 160 if (lstat64 (dest, &stats) == 0)
9d141cae
UD
161 {
162 if (S_ISDIR (stats.st_mode))
163 {
cbbcaf23 164 fprintf (stderr, _("%s: destination must not be a directory\n"),
350635a5 165 dest);
ba9fcb3f 166 return 1;
9d141cae
UD
167 }
168 else if (unlink (dest) && errno != ENOENT)
169 {
cbbcaf23 170 fprintf (stderr, _("%s: failed to remove the old destination\n"),
350635a5 171 dest);
ba9fcb3f 172 return 1;
9d141cae
UD
173 }
174 }
175 else if (errno != ENOENT)
176 {
177 error = strerror (errno);
cbbcaf23 178 fprintf (stderr, _("%s: invalid destination: %s\n"), dest, error);
9d141cae
UD
179 return -1;
180 }
df777c40 181
9d141cae 182 if (symlink (src, dest) == 0)
9d141cae
UD
183 {
184 /* Destination must exist by now. */
185 if (access (dest, F_OK))
186 {
187 error = strerror (errno);
188 unlink (dest);
cbbcaf23 189 fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
350635a5 190 src, dest, error);
ba9fcb3f 191 return 1;
9d141cae
UD
192 }
193 return 0;
194 }
195 else
196 {
197 error = strerror (errno);
cbbcaf23 198 fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
350635a5 199 src, dest, error);
ba9fcb3f 200 return 1;
9d141cae
UD
201 }
202}