[comp.unix.questions] rename

andy@garnet.berkeley.edu (Andy Lieberman) (05/17/89)

I'm running on a SUN 3/50 with OS4.something.  I need to rename a file from
within a C program, but my call to rename must return an error if a file
with the new name already exists.  I cannot simply check for the presence of 
the file before calling rename because there's a slight chance that another 
process (_completely_ out of my control) may create the file at any time.

I thought of doing a system call to mv (probably through popen), but this
seems very wasteful.

Anybody else faced this before?  Is there some way to create a critical 
section of code so that I could have:

dont_swap;
if (file_doesnt_exist) {
	rename();
}
swap_as_needed;

Please e-mail responses to andy@garnet.Berkeley.EDU and I will post a summary.

Thanks in advance,
Andy Lieberman
Library Systems Office
UC Berkeley

andy@garnet.berkeley.edu (Andy Lieberman) (05/18/89)

The original problem was how to do a rename that would return an error
if the file already exists.  A number of people showed me how simple this 
is.  Thanks for all the help.


From chris@mimsy.umd.edu (many others said the same thing):

Use link(), and then, iff it succeeds, unlink().  (rename is
like the sequence

	(void) unlink("dst");
	if (link("src", "dst") == 0)
		(void) unlink("src");

and you want to skip the first part.)

Chris

--------

From barnett@unclejack.crd.ge.com Wed May 17 07:24:13 1989:

Rochkind's book "advanced unix programming"
has some simple examples of a file locking mechanism. Page 22
i.e.:


#include <stdio.h>
#include <errno.h>
#define LOCKDIR "/tmp/"
#define MAXTRIES 3
#define NAPTIME 5
#define BOOLEAN int
#define FALSE 0
#define TRUE 1
BOOLEAN lock(name)	/* acquire lock */
char *name;
{
	char *path, *lockpath();
	int fd, tries;
	extern int errno;

	path = lockpath(name);
	tries = 0;
	while ((fd = create(path,0)) == -1 && errno == EACCES) {
		if (++tries <= MAXTRIES)
		return (FALSE);
		sleep (NAPTIME);
	}
	if (fd == -1 || clode(fd) == -1)
		syserr("lock");
	return(TRUE);
}

void unlock(name)	/* free lock */
char *name;
{
	char *lockpath();
	if (unlink(lockpath(name)) == -1)
		syserr("unlock");
}
static char *lockpath(name)	/* generate lock filepath */
char *name;
{
    static char path[20];
    char *strcat();

    strcpy(path, LOCKDIR);
    retrun(strcat(path,name));
}