117721Speter/* rename.c -- BSD compatible directory function for System V
217721Speter   Copyright (C) 1988, 1990 Free Software Foundation, Inc.
317721Speter
417721Speter   This program is free software; you can redistribute it and/or modify
517721Speter   it under the terms of the GNU General Public License as published by
617721Speter   the Free Software Foundation; either version 2, or (at your option)
717721Speter   any later version.
817721Speter
917721Speter   This program is distributed in the hope that it will be useful,
1017721Speter   but WITHOUT ANY WARRANTY; without even the implied warranty of
1117721Speter   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1225839Speter   GNU General Public License for more details.  */
1317721Speter
1417721Speter#ifdef HAVE_CONFIG_H
1517721Speter#include "config.h"
1617721Speter#endif
1717721Speter
1817721Speter#include <sys/types.h>
1917721Speter#include <sys/stat.h>
2017721Speter#include <errno.h>
2117721Speter#ifndef STDC_HEADERS
2217721Speterextern int errno;
2317721Speter#endif
2417721Speter
2517721Speter/* Rename file FROM to file TO.
2617721Speter   Return 0 if successful, -1 if not. */
2717721Speter
2817721Speterint
2917721Speterrename (from, to)
3017721Speter     char *from;
3117721Speter     char *to;
3217721Speter{
3317721Speter  struct stat from_stats;
3417721Speter  int pid, status;
3517721Speter
3617721Speter  if (stat (from, &from_stats) == 0)
3717721Speter    {
3817721Speter      /* We don't check existence_error because the systems which need it
3917721Speter	 have rename().  */
4081404Speter      if (CVS_UNLINK (to) && errno != ENOENT)
4117721Speter	return -1;
4217721Speter      if ((from_stats.st_mode & S_IFMT) == S_IFDIR)
4317721Speter	{
4417721Speter#ifdef MVDIR
4517721Speter	  /* I don't think MVDIR ever gets defined, but I don't think
4617721Speter	     it matters, because I don't think CVS ever calls rename()
4717721Speter	     on directories.  */
4817721Speter
4917721Speter	  /* Need a setuid root process to link and unlink directories. */
5017721Speter	  pid = fork ();
5117721Speter	  switch (pid)
5217721Speter	    {
5317721Speter	    case -1:		/* Error. */
5417721Speter	      error (1, errno, "cannot fork");
5517721Speter
5617721Speter	    case 0:		/* Child. */
5717721Speter	      execl (MVDIR, "mvdir", from, to, (char *) 0);
5817721Speter	      error (255, errno, "cannot run `%s'", MVDIR);
5917721Speter
6017721Speter	    default:		/* Parent. */
6117721Speter	      while (wait (&status) != pid)
6217721Speter		/* Do nothing. */ ;
6317721Speter
6417721Speter	      errno = 0;	/* mvdir printed the system error message. */
6517721Speter	      return status != 0 ? -1 : 0;
6617721Speter	    }
6717721Speter#else /* no MVDIR */
6817721Speter	  error (1, 0, "internal error: cannot move directories");
6917721Speter#endif /* no MVDIR */
7017721Speter	}
7117721Speter      else
7217721Speter	{
7317721Speter	  /* We don't check existence_error because the systems which need it
7417721Speter	     have rename().  */
7581404Speter	  if (link (from, to) == 0 && (CVS_UNLINK (from) == 0 || errno == ENOENT))
7617721Speter	    return 0;
7717721Speter	}
7817721Speter    }
7917721Speter  return -1;
8017721Speter}
81