Add changelog.
[glibc.git] / elf / sln.c
blobbe39fe41d5b17ecd059e0abb7e2aa9a59de6acdd
1 /* `sln' program to create symbolic links between files.
2 Copyright (C) 1998-2013 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 (file)
91 const char *file;
93 #ifndef PATH_MAX
94 #define PATH_MAX 4095
95 #endif
96 char *buffer = NULL;
97 size_t bufferlen = 0;
98 int ret;
99 int lineno;
100 FILE *fp;
102 if (strcmp (file, "-") == 0)
103 fp = stdin;
104 else
106 fp = fopen (file, "r");
107 if (fp == NULL)
109 fprintf (stderr, _("%s: file open error: %m\n"), file);
110 return 1;
114 ret = 0;
115 lineno = 0;
116 while (!feof_unlocked (fp))
118 ssize_t n = getline (&buffer, &bufferlen, fp);
119 char *src;
120 char *dest;
121 char *cp = buffer;
123 if (n < 0)
124 break;
125 if (buffer[n - 1] == '\n')
126 buffer[n - 1] = '\0';
128 ++lineno;
129 while (isspace (*cp))
130 ++cp;
131 if (*cp == '\0')
132 /* Ignore empty lines. */
133 continue;
134 src = cp;
137 ++cp;
138 while (*cp != '\0' && ! isspace (*cp));
139 if (*cp != '\0')
140 *cp++ = '\0';
142 while (isspace (*cp))
143 ++cp;
144 if (*cp == '\0')
146 fprintf (stderr, _("No target in line %d\n"), lineno);
147 ret = 1;
148 continue;
150 dest = cp;
153 ++cp;
154 while (*cp != '\0' && ! isspace (*cp));
155 if (*cp != '\0')
156 *cp++ = '\0';
158 ret |= makesymlink (src, dest);
160 fclose (fp);
162 return ret;
165 static int
166 makesymlink (src, dest)
167 const char *src;
168 const char *dest;
170 struct stat stats;
171 const char *error;
173 /* Destination must not be a directory. */
174 if (lstat (dest, &stats) == 0)
176 if (S_ISDIR (stats.st_mode))
178 fprintf (stderr, _("%s: destination must not be a directory\n"),
179 dest);
180 return 1;
182 else if (unlink (dest) && errno != ENOENT)
184 fprintf (stderr, _("%s: failed to remove the old destination\n"),
185 dest);
186 return 1;
189 else if (errno != ENOENT)
191 error = strerror (errno);
192 fprintf (stderr, _("%s: invalid destination: %s\n"), dest, error);
193 return -1;
196 #ifdef S_ISLNK
197 if (symlink (src, dest) == 0)
198 #else
199 if (link (src, dest) == 0)
200 #endif
202 /* Destination must exist by now. */
203 if (access (dest, F_OK))
205 error = strerror (errno);
206 unlink (dest);
207 fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
208 src, dest, error);
209 return 1;
211 return 0;
213 else
215 error = strerror (errno);
216 fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
217 src, dest, error);
218 return 1;