home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gnulib / libsrc98.zoo / rename.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-24  |  3.9 KB  |  164 lines

  1. /* a public domain rename, by ERS */
  2.  
  3. #include <stdio.h>
  4. #include <errno.h>
  5. #include <osbind.h>
  6. #include <unistd.h>
  7. #include <support.h>
  8. #include <string.h>
  9. #include <stdlib.h>
  10. #include "symdir.h"
  11.  
  12. int rename(_oldname, _newname)
  13.     const char *_oldname, *_newname;
  14. {
  15.     char oldname[FILENAME_MAX], newname[FILENAME_MAX];
  16.     char oldpath[FILENAME_MAX];
  17.     int rval, name_munged;
  18.     SYMDIR *olddir = 0, *newdir = 0;
  19.     SYMENTRY *ent = 0, *old;
  20.     char *s;
  21.     int save_errno = errno;
  22.  
  23.     if (!access(_newname, 0)) {    /* new name already exists */
  24. #ifdef DEBUG
  25. printf("rename: unlinking %s\n", _newname);
  26. #endif
  27.         if (unlink(_newname))
  28.             return -1;
  29.     }
  30.     errno = save_errno;
  31.  
  32.     rval = _unx2dos(_oldname, oldname);
  33.     /* _unx2dos returns _NM_LINK and sets __link_path and __link_name if
  34.          * given a symbolic link
  35.      */
  36.     if (rval == _NM_LINK) {            /* a symbolic link */
  37.         strcpy(oldpath, __link_path);    /* save path to symlink */
  38.         olddir = _read_symdir(oldpath);
  39.         if (!olddir) return -1;
  40.         old = 0; ent = olddir->s_dir;
  41.         while (ent) {
  42.             if (!strcmp(ent->linkname, __link_name)) {
  43. #ifdef DEBUG
  44. printf("rename: found symbolic link %s\n", __link_name);
  45. #endif
  46.                 break;
  47.             }
  48.             old = ent; ent = ent->next;
  49.         }
  50.         if (!ent) { 
  51.             errno = EERROR; _free_symdir(olddir); return -1;
  52.         }
  53.         if (old)
  54.             old->next = ent->next;
  55.         else
  56.             olddir->s_dir = ent->next;
  57.         ent->next = 0;
  58.         _write_symdir(oldpath, olddir);
  59.         _free_symdir(olddir);
  60.     }
  61.  
  62. /*
  63.  * save info about whether or not the name got changed by _unx2dos
  64.  */
  65.     name_munged = (_unx2dos(_newname, newname) == _NM_CHANGE);
  66. /*
  67.  * for a symbolic link, we now have an entry "ent" which points at
  68.  * the old symbolic link. Make a new symbolic link, with the new name,
  69.  * in the new directory. EXCEPTION: automatic symbolic links get handled
  70.  * later.
  71.  */
  72.     if (ent && !(ent->flags & SD_AUTO)) {
  73.         if ((s = strrchr(newname, '\\')))
  74.             *s = 0;
  75.         if (!s || !(newdir = _read_symdir(newname))) {
  76. link_failed:
  77. #ifdef DEBUG
  78. printf("rename: attempt to link to directory %s failed\n", newname);
  79. #endif
  80.     /* if we can't put the symlink into the new directory, put it
  81.          * back in the old one again
  82.          */
  83.             olddir = _read_symdir(oldpath);
  84.             if (olddir) {
  85.                 ent->next = olddir->s_dir;
  86.                 olddir->s_dir = ent;
  87.                 _write_symdir(oldpath, olddir);
  88.                 _free_symdir(olddir);
  89.             }
  90.             return -1;
  91.         }
  92.     /* OK, now allocate a new symentry to hold the new name and link
  93.          * info. Note that "old" is definitely a misnomer here!!!
  94.          */
  95.         old = (SYMENTRY *)malloc(3+sizeof(SYMENTRY)+
  96.             strlen(__link_name)+strlen(ent->linkto)+strlen(ent->cflags)
  97.            );
  98.         if (!old) {
  99.             errno = ENOMEM;
  100.             goto link_failed;
  101.         }
  102.     /*
  103.      * Now copy all the fields of "ent" into the new symentry
  104.      * (which is, contrary to reason, called "old"; actually, this
  105.          * is so that on an error we can "goto link_failed" and restore
  106.          * the status quo).
  107.      */ 
  108.         s = old->linkname;
  109.         strcpy(old->linkname, __link_name);
  110.         s += strlen(__link_name)+1;
  111.         old->linkto = s;
  112.         strcpy(s, ent->linkto);
  113.         s += strlen(ent->linkto)+1;
  114.         old->cflags = s;
  115.         strcpy(s, ent->cflags);
  116.         free(ent);
  117.         old->next = newdir->s_dir;
  118.         newdir->s_dir = old;
  119.     /*
  120.      * update the copy on disk, and return
  121.      */
  122. #ifdef DEBUG
  123. printf("rename: updating symbolic link info\n");
  124. #endif
  125.         rval = _write_symdir(newname, newdir);
  126.         _free_symdir(newdir);
  127.         if (rval) {
  128.             errno = -rval;
  129.             return -1;
  130.         }
  131.         return 0;
  132.     }
  133.  
  134. /*
  135.  * normal files, and automatic symbolic links, come here
  136.  */
  137. #ifdef DEBUG
  138. printf("rename: calling Frename(%s, %s)\n", oldname, newname);
  139. #endif
  140.     if (!strcmp(oldname, newname)) {
  141.         rval = 0;
  142.     }
  143.     else if ( (rval = Frename(0, oldname, newname)) < 0 ) {
  144.         errno = -rval;    /* set errno now for link_failed */
  145.         rval = -1;
  146.     }
  147.     if (ent) {
  148.         if (rval < 0)
  149.             goto link_failed;
  150.         else {
  151.             free(ent);
  152.             ent = 0;
  153.         }
  154.     }
  155. /*
  156.  * finally, check to see if the new name should have an automatic symbolic
  157.  * link attached
  158.  */
  159.     if (rval == 0 && name_munged)
  160.         _make_autolink(newname, __link_name);
  161.  
  162.     return rval;
  163. }
  164.