home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / gnu / djgpp / libsrc / c / sys / link.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-21  |  2.5 KB  |  99 lines

  1. /*
  2.   (c) Copyright 1992 Eric Backus
  3.  
  4.   This software may be used freely so long as this copyright notice is
  5.   left intact.  There is no warrantee on this software.
  6. */
  7.  
  8. #include <sys/stat.h>        /* For stat() */
  9. #include <fcntl.h>        /* For O_RDONLY, etc. */
  10. #include <unistd.h>        /* For read(), write(), etc. */
  11. #include <limits.h>        /* For PATH_MAX */
  12. #include <utime.h>        /* For utime() */
  13. #include <errno.h>        /* For errno */
  14.  
  15. extern void _fixpath(const char *, char *);
  16.  
  17. /* Of course, DOS can't really do a link.  We just do a copy instead,
  18.    which is as close as DOS gets.  Alternatively, we could always fail
  19.    and return -1.  I think this is slightly better. */
  20. int
  21. link(const char *path1, const char *path2)
  22. {
  23.     struct stat        statbuf;
  24.     struct utimbuf    times;
  25.     char    p1[PATH_MAX + 1], p2[PATH_MAX + 1];
  26.     char    buf[2048];
  27.     int        fd1, fd2, nbyte, status1, status2;
  28.  
  29.     /* Fail if either path is null */
  30.     if (path1 == NULL || *path1 == '\0' ||
  31.     path2 == NULL || *path2 == '\0')
  32.     {
  33.     errno = ENOENT;
  34.     return -1;
  35.     }
  36.  
  37.     _fixpath(path1, p1);
  38.     _fixpath(path2, p2);
  39.  
  40.     /* Fail if path1 does not exist - stat() will set errno */
  41.     if (stat(p1, &statbuf) < 0) return -1;
  42.  
  43.     /* Fail if path1 is not a regular file */
  44.     if ((statbuf.st_mode & S_IFMT) != S_IFREG)
  45.     {
  46.     errno = EPERM;
  47.     return -1;
  48.     }
  49.  
  50.     /* Fail if path1 and path2 are on different devices */
  51.     if (p1[0] != p2[0])
  52.     {
  53.     errno = EXDEV;
  54.     return -1;
  55.     }
  56.  
  57.     /* Fail if unable to open path1 - open() will set errno */
  58.     fd1 = open(p1, O_RDONLY | O_BINARY);
  59.     if (fd1 < 0) return -1;
  60.  
  61.     /* Fail if unable to create path2 - open() will set errno */
  62.     fd2 = open(p2, O_WRONLY | O_BINARY | O_CREAT | O_EXCL, 0600);
  63.     if (fd2 < 0)
  64.     {
  65.     (void) close(fd1);
  66.     return -1;
  67.     }
  68.  
  69.     /* Copy path1 to path2 */
  70.     do
  71.     {
  72.     nbyte = read(fd1, buf, sizeof buf);
  73.     if (nbyte <= 0) break;
  74.     if (write(fd2, buf, nbyte) != nbyte) nbyte = -1;
  75.     }
  76.     while (nbyte > 0);
  77.  
  78.     /* Fail if the copy failed or we can't clean up */
  79.     status1 = close(fd1);
  80.     status2 = close(fd2);
  81.     if (nbyte < 0 || status1 < 0 || status2 < 0)
  82.     {
  83.     (void) unlink(path2);
  84.     return -1;
  85.     }
  86.  
  87.     /* Success! */
  88.  
  89.     /* Set the mode to match the original, ignoring errors */
  90.     (void) chmod(p2, statbuf.st_mode);
  91.  
  92.     /* Set the file time to match the original, ignoring errors */
  93.     times.actime = statbuf.st_atime;
  94.     times.modtime = statbuf.st_mtime;
  95.     (void) utime(p2, ×);
  96.  
  97.     return 0;
  98. }
  99.