Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!rutgers!ucsd!ucbvax!hplabs!hpda!hptsug2!taylor@limbo.ptp.hp.com
From: taylor@limbo.ptp.hp.com (Dave Taylor)
Newsgroups: comp.sys.hp
Subject: Re: Compatible HP-UX 5.1 function "rename" from Berkley 4.3
Message-ID: <541@hptsug2.HP.COM>
Date: 24 Sep 88 05:29:51 GMT
References: <908@arctic.nprdc.arpa>
Sender: taylor@hptsug2.HP.COM
Organization: Hewlett-Packard University Grants Program
Lines: 134

A while back, while working on porting some BSD code to HP-UX,
I also had need for the rename() command.  What I ended up
doing was reading the BSD man page and attempting to duplicate
the behaviour of the command as much as possible -- I have
attached this routine below.  

Note: This comes to you with no warrantee or guarantee --- it
worked for the application I was porting, but your milage may
vary...
						-- Dave Taylor

Technical Project Team
University Grants Program
Hewlett-Packard Company

----- attachment: "rename.c"

/**			rename.c		**/

/** This is a short routine to emulate the Berkeley rename() function.
    The function is defined as:

       rename(from, to)
       char *from, *to;

        Rename causes the link named `from' to be renamed as `to'.  If `to'
        exists then it is first removed.  Both `from' and `to' must be of
	the same type (that is, both directories or both non-directories),
	and must reside on the same file system.

	Rename guarantees that an instance of `to' will always exist, even
	if the system should crash in the middle of the operation.

	A 0 value is returned if the operation succeeds, otherwise a -1 is
	returned and ERRNO is set accordingly.

    What our function does is attempt as much as possible to preserve the
    functionality listed above.  The tough part is ensure that we are 
    never at a point where we might lose both copies of the file...

    Dave Taylor, Hewlett-Packard Labs, May 1987
    with additional code by Debbie Caswell, HP Labs
**/

#include 
#include 

extern int errno;

char *base_directory_name();

rename(from, to)
char *from, *to;
{
	char tempfname[256];

	/* valid parameters?? */

	if ((to == 0 || *to == 0) || (from == 0 || *from == 0)) {
	  errno = ENOENT;
	  return(-1);
	}

	/* next let's create the tempfile and save 'to' for luck */

	sprintf(tempfname, "%s/rename.%d", base_directory_name(from), getpid());

	if (link(to, tempfname) != 0) {
	  if (errno != ENOENT) {	/* NOENT is no problem .. continue */
#ifdef DEBUG
	    fprintf(stderr, 
		    "rename: Couldn't make the initial link of %s to %s\n",
		    to, tempfname);
#endif
	    return(-1);
	  }
	}
	
	(void) unlink(to);

	if (link(from, to) != 0) {
	  if (link(tempfname, to) != 0)
#ifdef DEBUG
	    fprintf(stderr,"rename: couldn't restore %s.  Left as %s instead\n",
			   to, tempfname);
	  else
	    fprintf(stderr,"rename: couldn't link %s to %s.  Left both.\n",
			   from, to);
#else
	  /* nothing to do */		;
#endif
	  return(-1);
	}

	/* linked okay, so let's get rid of the tempfile */

	(void) unlink(tempfname);

	/* and the 'from' file.. */

	(void) unlink(from);

	/* and return no errors */

	return(0);
}

char *base_directory_name(filename)
char *filename;
{
	/** this returns a pointer to either the directory name 
	    specified or to "." if no directory is specified as part
	    of the given filename.
	**/

	static char mybuffer[256];
	char   *ptr;
	
	strcpy(mybuffer, filename);

	ptr = mybuffer + strlen(mybuffer);

	while (*ptr != '/' && ptr != mybuffer)
	  ptr--;
	
	if (*ptr == '/') 
	  *ptr = '\0';
	else
	  strcpy(mybuffer, ".");

	return( (char *) mybuffer);
}

/***** end of rename.c *****/