[comp.sys.hp] Compatible HP-UX 5.1 function "rename" from Berkley 4.3

carroll@nprdc.arpa (Larry Carroll) (09/23/88)

Is there a compatible function "rename" (Berkley 4.3)
available on HP-UX 5.1 ?

I prefer not to use the HP-UX "system" function as it 
would slow performance.

Thanks in advance for your reply...


Larry Carroll			"Stop the world, I want to get off!"
ucsd!nprdc!carroll

Navy Personnel Research and Development Center
San Diego, CA

taylor@limbo.ptp.hp.com (Dave Taylor) (09/24/88)

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 <stdio.h>
#include <errno.h>

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 *****/

gwc@root.co.uk (Geoff Clare) (09/27/88)

In article <541@hptsug2.HP.COM> taylor@limbo.ptp.hp.com (Dave Taylor) writes:
>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
>  [ code deleted ]
>

Dave's version seems unnecessarily complex to me.  Here's the one I use:

extern int errno;

rename(src, dest)
char *src, *dest;
{
	if (link(src, dest) != 0)
		return -1;
	if (unlink(src) != 0)
	{
		int err = errno;
		(void) unlink(dest);
		errno = err;
		return -1;
	}
	return 0;
}

-- 

Geoff Clare    UniSoft Limited, Saunderson House, Hayne Street, London EC1A 9HH
gwc@root.co.uk   ...!mcvax!ukc!root44!gwc   +44-1-606-7799  FAX: +44-1-726-2750