home *** CD-ROM | disk | FTP | other *** search
- /* a public domain rename, by ERS */
-
- #include <stdio.h>
- #include <errno.h>
- #include <osbind.h>
- #include <unistd.h>
- #include <support.h>
- #include <string.h>
- #include <stdlib.h>
- #include "symdir.h"
-
- int rename(_oldname, _newname)
- const char *_oldname, *_newname;
- {
- char oldname[FILENAME_MAX], newname[FILENAME_MAX];
- char oldpath[FILENAME_MAX];
- int rval, name_munged;
- SYMDIR *olddir = 0, *newdir = 0;
- SYMENTRY *ent = 0, *old;
- char *s;
- int save_errno = errno;
-
- if (!access(_newname, 0)) { /* new name already exists */
- #ifdef DEBUG
- printf("rename: unlinking %s\n", _newname);
- #endif
- if (unlink(_newname))
- return -1;
- }
- errno = save_errno;
-
- rval = _unx2dos(_oldname, oldname);
- /* _unx2dos returns _NM_LINK and sets __link_path and __link_name if
- * given a symbolic link
- */
- if (rval == _NM_LINK) { /* a symbolic link */
- strcpy(oldpath, __link_path); /* save path to symlink */
- olddir = _read_symdir(oldpath);
- if (!olddir) return -1;
- old = 0; ent = olddir->s_dir;
- while (ent) {
- if (!strcmp(ent->linkname, __link_name)) {
- #ifdef DEBUG
- printf("rename: found symbolic link %s\n", __link_name);
- #endif
- break;
- }
- old = ent; ent = ent->next;
- }
- if (!ent) {
- errno = EERROR; _free_symdir(olddir); return -1;
- }
- if (old)
- old->next = ent->next;
- else
- olddir->s_dir = ent->next;
- ent->next = 0;
- _write_symdir(oldpath, olddir);
- _free_symdir(olddir);
- }
-
- /*
- * save info about whether or not the name got changed by _unx2dos
- */
- name_munged = (_unx2dos(_newname, newname) == _NM_CHANGE);
- /*
- * for a symbolic link, we now have an entry "ent" which points at
- * the old symbolic link. Make a new symbolic link, with the new name,
- * in the new directory. EXCEPTION: automatic symbolic links get handled
- * later.
- */
- if (ent && !(ent->flags & SD_AUTO)) {
- if ((s = strrchr(newname, '\\')))
- *s = 0;
- if (!s || !(newdir = _read_symdir(newname))) {
- link_failed:
- #ifdef DEBUG
- printf("rename: attempt to link to directory %s failed\n", newname);
- #endif
- /* if we can't put the symlink into the new directory, put it
- * back in the old one again
- */
- olddir = _read_symdir(oldpath);
- if (olddir) {
- ent->next = olddir->s_dir;
- olddir->s_dir = ent;
- _write_symdir(oldpath, olddir);
- _free_symdir(olddir);
- }
- return -1;
- }
- /* OK, now allocate a new symentry to hold the new name and link
- * info. Note that "old" is definitely a misnomer here!!!
- */
- old = (SYMENTRY *)malloc(3+sizeof(SYMENTRY)+
- strlen(__link_name)+strlen(ent->linkto)+strlen(ent->cflags)
- );
- if (!old) {
- errno = ENOMEM;
- goto link_failed;
- }
- /*
- * Now copy all the fields of "ent" into the new symentry
- * (which is, contrary to reason, called "old"; actually, this
- * is so that on an error we can "goto link_failed" and restore
- * the status quo).
- */
- s = old->linkname;
- strcpy(old->linkname, __link_name);
- s += strlen(__link_name)+1;
- old->linkto = s;
- strcpy(s, ent->linkto);
- s += strlen(ent->linkto)+1;
- old->cflags = s;
- strcpy(s, ent->cflags);
- free(ent);
- old->next = newdir->s_dir;
- newdir->s_dir = old;
- /*
- * update the copy on disk, and return
- */
- #ifdef DEBUG
- printf("rename: updating symbolic link info\n");
- #endif
- rval = _write_symdir(newname, newdir);
- _free_symdir(newdir);
- if (rval) {
- errno = -rval;
- return -1;
- }
- return 0;
- }
-
- /*
- * normal files, and automatic symbolic links, come here
- */
- #ifdef DEBUG
- printf("rename: calling Frename(%s, %s)\n", oldname, newname);
- #endif
- if (!strcmp(oldname, newname)) {
- rval = 0;
- }
- else if ( (rval = Frename(0, oldname, newname)) < 0 ) {
- errno = -rval; /* set errno now for link_failed */
- rval = -1;
- }
- if (ent) {
- if (rval < 0)
- goto link_failed;
- else {
- free(ent);
- ent = 0;
- }
- }
- /*
- * finally, check to see if the new name should have an automatic symbolic
- * link attached
- */
- if (rval == 0 && name_munged)
- _make_autolink(newname, __link_name);
-
- return rval;
- }
-