nptl: Add more coverage in tst-cancel4
[glibc.git] / elf / sln.c
blobf52cb9f44a85bbeb83933b1b497db85232ef85c8
1 /* `sln' program to create symbolic links between files.
2 Copyright (C) 1998-2016 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
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.
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
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
23 #include <error.h>
24 #include <errno.h>
25 #include <libintl.h>
26 #include <locale.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <limits.h>
36 #include "../version.h"
38 #define PACKAGE _libc_intl_domainname
40 #if !defined S_ISDIR && defined S_IFDIR
41 #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
42 #endif
44 static int makesymlink (const char *src, const char *dest);
45 static int makesymlinks (const char *file);
46 static void usage (void);
48 int
49 main (int argc, char **argv)
51 /* Set locale via LC_ALL. */
52 setlocale (LC_ALL, "");
54 /* Set the text message domain. */
55 textdomain (PACKAGE);
57 switch (argc)
59 case 2:
60 if (strcmp (argv[1], "--version") == 0) {
61 printf ("sln %s%s\n", PKGVERSION, VERSION);
62 return 0;
63 } else if (strcmp (argv[1], "--help") == 0) {
64 usage ();
65 return 0;
67 return makesymlinks (argv [1]);
68 break;
70 case 3:
71 return makesymlink (argv [1], argv [2]);
72 break;
74 default:
75 usage ();
76 return 1;
77 break;
81 static void
82 usage (void)
84 printf (_("Usage: sln src dest|file\n\n"));
85 printf (_("For bug reporting instructions, please see:\n\
86 %s.\n"), REPORT_BUGS_TO);
89 static int
90 makesymlinks (const char *file)
92 #ifndef PATH_MAX
93 #define PATH_MAX 4095
94 #endif
95 char *buffer = NULL;
96 size_t bufferlen = 0;
97 int ret;
98 int lineno;
99 FILE *fp;
101 if (strcmp (file, "-") == 0)
102 fp = stdin;
103 else
105 fp = fopen (file, "r");
106 if (fp == NULL)
108 fprintf (stderr, _("%s: file open error: %m\n"), file);
109 return 1;
113 ret = 0;
114 lineno = 0;
115 while (!feof_unlocked (fp))
117 ssize_t n = getline (&buffer, &bufferlen, fp);
118 char *src;
119 char *dest;
120 char *cp = buffer;
122 if (n < 0)
123 break;
124 if (buffer[n - 1] == '\n')
125 buffer[n - 1] = '\0';
127 ++lineno;
128 while (isspace (*cp))
129 ++cp;
130 if (*cp == '\0')
131 /* Ignore empty lines. */
132 continue;
133 src = cp;
136 ++cp;
137 while (*cp != '\0' && ! isspace (*cp));
138 if (*cp != '\0')
139 *cp++ = '\0';
141 while (isspace (*cp))
142 ++cp;
143 if (*cp == '\0')
145 fprintf (stderr, _("No target in line %d\n"), lineno);
146 ret = 1;
147 continue;
149 dest = cp;
152 ++cp;
153 while (*cp != '\0' && ! isspace (*cp));
154 if (*cp != '\0')
155 *cp++ = '\0';
157 ret |= makesymlink (src, dest);
159 fclose (fp);
161 return ret;
164 static int
165 makesymlink (const char *src, const char *dest)
167 struct stat64 stats;
168 const char *error;
170 /* Destination must not be a directory. */
171 if (lstat64 (dest, &stats) == 0)
173 if (S_ISDIR (stats.st_mode))
175 fprintf (stderr, _("%s: destination must not be a directory\n"),
176 dest);
177 return 1;
179 else if (unlink (dest) && errno != ENOENT)
181 fprintf (stderr, _("%s: failed to remove the old destination\n"),
182 dest);
183 return 1;
186 else if (errno != ENOENT)
188 error = strerror (errno);
189 fprintf (stderr, _("%s: invalid destination: %s\n"), dest, error);
190 return -1;
193 #ifdef S_ISLNK
194 if (symlink (src, dest) == 0)
195 #else
196 if (link (src, dest) == 0)
197 #endif
199 /* Destination must exist by now. */
200 if (access (dest, F_OK))
202 error = strerror (errno);
203 unlink (dest);
204 fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
205 src, dest, error);
206 return 1;
208 return 0;
210 else
212 error = strerror (errno);
213 fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
214 src, dest, error);
215 return 1;