(root)/
glibc-2.38/
elf/
sln.c
       1  /* `sln' program to create symbolic links between files.
       2     Copyright (C) 1998-2023 Free Software Foundation, Inc.
       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
       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.
       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
      13     Lesser General Public License for more details.
      14  
      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     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <error.h>
      20  #include <errno.h>
      21  #include <libintl.h>
      22  #include <locale.h>
      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  
      32  #include "../version.h"
      33  
      34  #define PACKAGE _libc_intl_domainname
      35  
      36  static int makesymlink (const char *src, const char *dest);
      37  static int makesymlinks (const char *file);
      38  static void usage (void);
      39  
      40  int
      41  main (int argc, char **argv)
      42  {
      43    /* Set locale via LC_ALL.  */
      44    setlocale (LC_ALL, "");
      45  
      46    /* Set the text message domain.  */
      47    textdomain (PACKAGE);
      48  
      49    switch (argc)
      50      {
      51      case 2:
      52        if (strcmp (argv[1], "--version") == 0) {
      53  	printf ("sln %s%s\n", PKGVERSION, VERSION);
      54  	return 0;
      55        } else if (strcmp (argv[1], "--help") == 0) {
      56  	usage ();
      57  	return 0;
      58        }
      59        return makesymlinks (argv [1]);
      60        break;
      61  
      62      case 3:
      63        return makesymlink (argv [1], argv [2]);
      64        break;
      65  
      66      default:
      67        usage ();
      68        return 1;
      69        break;
      70      }
      71  }
      72  
      73  static void
      74  usage (void)
      75  {
      76    printf (_("Usage: sln src dest|file\n\n"));
      77    printf (_("For bug reporting instructions, please see:\n\
      78  %s.\n"), REPORT_BUGS_TO);
      79  }
      80  
      81  static int
      82  makesymlinks (const char *file)
      83  {
      84    char *buffer = NULL;
      85    size_t bufferlen = 0;
      86    int ret;
      87    int lineno;
      88    FILE *fp;
      89  
      90    if (strcmp (file, "-") == 0)
      91      fp = stdin;
      92    else
      93      {
      94        fp = fopen (file, "r");
      95        if (fp == NULL)
      96  	{
      97  	  fprintf (stderr, _("%s: file open error: %m\n"), file);
      98  	  return 1;
      99  	}
     100      }
     101  
     102    ret = 0;
     103    lineno = 0;
     104    while (!feof_unlocked (fp))
     105      {
     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')
     133  	{
     134  	  fprintf (stderr, _("No target in line %d\n"), lineno);
     135  	  ret = 1;
     136  	  continue;
     137  	}
     138        dest = cp;
     139  
     140        do
     141  	++cp;
     142        while (*cp != '\0' && ! isspace (*cp));
     143        if (*cp != '\0')
     144  	*cp++ = '\0';
     145  
     146        ret |= makesymlink (src, dest);
     147      }
     148    fclose (fp);
     149  
     150    return ret;
     151  }
     152  
     153  static int
     154  makesymlink (const char *src, const char *dest)
     155  {
     156    struct stat stats;
     157    const char *error;
     158  
     159    /* Destination must not be a directory. */
     160    if (lstat (dest, &stats) == 0)
     161      {
     162        if (S_ISDIR (stats.st_mode))
     163  	{
     164  	  fprintf (stderr, _("%s: destination must not be a directory\n"),
     165  		   dest);
     166  	  return 1;
     167  	}
     168        else if (unlink (dest) && errno != ENOENT)
     169  	{
     170  	  fprintf (stderr, _("%s: failed to remove the old destination\n"),
     171  		   dest);
     172  	  return 1;
     173  	}
     174      }
     175    else if (errno != ENOENT)
     176      {
     177        error = strerror (errno);
     178        fprintf (stderr, _("%s: invalid destination: %s\n"), dest, error);
     179        return -1;
     180      }
     181  
     182    if (symlink (src, dest) == 0)
     183      {
     184        /* Destination must exist by now. */
     185        if (access (dest, F_OK))
     186          {
     187  	  error = strerror (errno);
     188  	  unlink (dest);
     189  	  fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
     190  		   src, dest, error);
     191  	  return 1;
     192  	}
     193        return 0;
     194      }
     195    else
     196      {
     197        error = strerror (errno);
     198        fprintf (stderr, _("Invalid link from \"%s\" to \"%s\": %s\n"),
     199  	       src, dest, error);
     200        return 1;
     201      }
     202  }