This source file includes following definitions.
- initialize
 
- link
 
- rpl_link
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 #include <config.h>
  19 
  20 #include <unistd.h>
  21 
  22 #include <errno.h>
  23 #include <stdlib.h>
  24 #include <string.h>
  25 #include <sys/stat.h>
  26 
  27 #if !HAVE_LINK
  28 # if defined _WIN32 && ! defined __CYGWIN__
  29 
  30 #  define WIN32_LEAN_AND_MEAN
  31 #  include <windows.h>
  32 
  33 
  34 #  undef GetModuleHandle
  35 #  define GetModuleHandle GetModuleHandleA
  36 #  undef CreateHardLink
  37 #  define CreateHardLink CreateHardLinkA
  38 
  39 #  if !(_WIN32_WINNT >= _WIN32_WINNT_WINXP)
  40 
  41 
  42 #   define GetProcAddress \
  43      (void *) GetProcAddress
  44 
  45 
  46 typedef BOOL (WINAPI * CreateHardLinkFuncType) (LPCSTR lpFileName,
  47                                                 LPCSTR lpExistingFileName,
  48                                                 LPSECURITY_ATTRIBUTES lpSecurityAttributes);
  49 static CreateHardLinkFuncType CreateHardLinkFunc = NULL;
  50 static BOOL initialized = FALSE;
  51 
  52 static void
  53 initialize (void)
     
  54 {
  55   HMODULE kernel32 = GetModuleHandle ("kernel32.dll");
  56   if (kernel32 != NULL)
  57     {
  58       CreateHardLinkFunc =
  59         (CreateHardLinkFuncType) GetProcAddress (kernel32, "CreateHardLinkA");
  60     }
  61   initialized = TRUE;
  62 }
  63 
  64 #  else
  65 
  66 #   define CreateHardLinkFunc CreateHardLink
  67 
  68 #  endif
  69 
  70 int
  71 link (const char *file1, const char *file2)
     
  72 {
  73   char *dir;
  74   size_t len1 = strlen (file1);
  75   size_t len2 = strlen (file2);
  76 
  77 #  if !(_WIN32_WINNT >= _WIN32_WINNT_WINXP)
  78   if (!initialized)
  79     initialize ();
  80 #  endif
  81 
  82   if (CreateHardLinkFunc == NULL)
  83     {
  84       
  85       errno = EPERM;
  86       return -1;
  87     }
  88   
  89 
  90   if ((len1 && (file1[len1 - 1] == '/' || file1[len1 - 1] == '\\'))
  91       || (len2 && (file2[len2 - 1] == '/' || file2[len2 - 1] == '\\')))
  92     {
  93       
  94       struct stat st;
  95       if (stat (file1, &st))
  96         {
  97           if (errno == EOVERFLOW)
  98             
  99             errno = ENOTDIR;
 100           return -1;
 101         }
 102       if (!S_ISDIR (st.st_mode))
 103         errno = ENOTDIR;
 104       else
 105         errno = EPERM;
 106       return -1;
 107     }
 108   
 109 
 110   dir = strdup (file2);
 111   if (!dir)
 112     return -1;
 113   {
 114     struct stat st;
 115     char *p = strchr (dir, '\0');
 116     while (dir < p && (*--p != '/' && *p != '\\'));
 117     *p = '\0';
 118     if (p != dir && stat (dir, &st) != 0 && errno != EOVERFLOW)
 119       {
 120         free (dir);
 121         return -1;
 122       }
 123     free (dir);
 124   }
 125   
 126   if (CreateHardLinkFunc (file2, file1, NULL) == 0)
 127     {
 128       
 129 
 130 
 131       DWORD err = GetLastError ();
 132       switch (err)
 133         {
 134         case ERROR_ACCESS_DENIED:
 135           errno = EACCES;
 136           break;
 137 
 138         case ERROR_INVALID_FUNCTION:    
 139           errno = EPERM;
 140           break;
 141 
 142         case ERROR_NOT_SAME_DEVICE:
 143           errno = EXDEV;
 144           break;
 145 
 146         case ERROR_PATH_NOT_FOUND:
 147         case ERROR_FILE_NOT_FOUND:
 148           errno = ENOENT;
 149           break;
 150 
 151         case ERROR_INVALID_PARAMETER:
 152           errno = ENAMETOOLONG;
 153           break;
 154 
 155         case ERROR_TOO_MANY_LINKS:
 156           errno = EMLINK;
 157           break;
 158 
 159         case ERROR_ALREADY_EXISTS:
 160           errno = EEXIST;
 161           break;
 162 
 163         default:
 164           errno = EIO;
 165         }
 166       return -1;
 167     }
 168 
 169   return 0;
 170 }
 171 
 172 # else 
 173 
 174 #  error "This platform lacks a link function, and Gnulib doesn't provide a replacement. This is a bug in Gnulib."
 175 
 176 # endif 
 177 #else 
 178 
 179 # undef link
 180 
 181 
 182 int
 183 rpl_link (char const *file1, char const *file2)
     
 184 {
 185   size_t len1;
 186   size_t len2;
 187   struct stat st;
 188 
 189   
 190   if (lstat (file2, &st) == 0 || errno == EOVERFLOW)
 191     {
 192       errno = EEXIST;
 193       return -1;
 194     }
 195 
 196   
 197   len1 = strlen (file1);
 198   len2 = strlen (file2);
 199   if ((len1 && file1[len1 - 1] == '/')
 200       || (len2 && file2[len2 - 1] == '/'))
 201     {
 202       
 203 
 204 
 205 
 206       if (stat (file1, &st))
 207         return -1;
 208       if (!S_ISDIR (st.st_mode))
 209         {
 210           errno = ENOTDIR;
 211           return -1;
 212         }
 213     }
 214   else
 215     {
 216       
 217       char *dir = strdup (file2);
 218       char *p;
 219       if (!dir)
 220         return -1;
 221       
 222 
 223       p = strrchr (dir, '/');
 224       if (p)
 225         {
 226           *p = '\0';
 227           if (stat (dir, &st) != 0 && errno != EOVERFLOW)
 228             {
 229               free (dir);
 230               return -1;
 231             }
 232         }
 233       free (dir);
 234     }
 235   return link (file1, file2);
 236 }
 237 #endif