Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / librols / rename.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)rename.c 1.6 04/09/04 Copyright 1998-2003 J. Schilling */
14 /*
15  *      rename() for old systems that don't have it.
16  *
17  *      Copyright (c) 1998-2003 J. Schilling
18  */
19 /*
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License version 2
22  * as published by the Free Software Foundation.
23  *
24  * This program is distributed in the hope that it will be useful,
25  * but WITHOUT ANY WARRANTY; without even the implied warranty of
26  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27  * GNU General Public License for more details.
28  *
29  * You should have received a copy of the GNU General Public License along with
30  * this program; see the file COPYING.  If not, write to the Free Software
31  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
32  */
33
34 #define rename  __nothing__
35 #include <mconfig.h>
36
37 #ifndef HAVE_RENAME
38
39 #include <stdio.h>      /* XXX not OK but needed for js_xx() in schily.h */
40 #include <unixstd.h>
41 #include <strdefs.h>
42 #include <statdefs.h>
43 #include <maxpath.h>
44 #include <standard.h>
45 #include <utypes.h>
46 #include <schily.h>
47 #include <errno.h>
48 #undef  rename
49 #include <libport.h>
50
51 #ifndef MAXPATHNAME
52 #define MAXPATHNAME     1024
53 #endif
54
55 #if     MAXPATHNAME < 1024
56 #undef  MAXPATHNAME
57 #define MAXPATHNAME     1024
58 #endif
59
60 #define MAXNAME MAXPATHNAME
61
62 #define FILEDESC struct stat
63
64 #ifndef HAVE_LSTAT
65 #define lstat   stat
66 #endif
67
68 EXPORT int
69 rename(old, new)
70         const char      *old;
71         const char      *new;
72 {
73         char    nname[MAXNAME];
74         char    bakname[MAXNAME];
75         char    strpid[32];
76         int     strplen;
77         BOOL    savpresent = FALSE;
78         BOOL    newpresent = FALSE;
79         int     serrno;
80         FILEDESC ostat;
81         FILEDESC xstat;
82
83         serrno = geterrno();
84
85         if (lstat(old, &ostat) < 0)
86                 return (-1);
87
88         if (lstat(new, &xstat) >= 0) {
89                 newpresent = TRUE;
90                 if (ostat.st_dev == xstat.st_dev &&
91                     ostat.st_ino == xstat.st_ino)
92                         return (0);             /* old == new we are done */
93         }
94
95         strplen = snprintf(strpid, sizeof (strpid), ".%lld",
96                                                         (Llong)getpid());
97
98         if (strlen(new) <= (MAXNAME-strplen) ||
99             strchr(&new[MAXNAME-strplen], '/') == NULL) {
100                 /*
101                  * Save old version of file 'new'.
102                  */
103                 strncpy(nname, new, MAXNAME-strplen);
104                 nname[MAXNAME-strplen] = '\0';
105                 snprintf(bakname, sizeof (bakname), "%s%s", nname, strpid);
106                 unlink(bakname);
107                 if (link(new, bakname) >= 0)
108                         savpresent = TRUE;
109         }
110
111         if (newpresent) {
112                 if (rmdir(new) < 0) {
113                         if (geterrno() == ENOTDIR) {
114                                 if (unlink(new) < 0)
115                                         return (-1);
116                         } else {
117                                 return (-1);
118                         }
119                 }
120         }
121
122         /*
123          * Now add 'new' name to 'old'.
124          */
125         if (link(old, new) < 0) {
126                 serrno = geterrno();
127                 /*
128                  * Make sure not to loose old version of 'new'.
129                  */
130                 if (savpresent) {
131                         unlink(new);
132                         link(bakname, new);
133                         unlink(bakname);
134                 }
135                 seterrno(serrno);
136                 return (-1);
137         }
138         if (unlink(old) < 0)
139                 return (-1);
140         unlink(bakname);                /* Fails in most cases...       */
141         seterrno(serrno);               /* ...so restore errno          */
142         return (0);
143 }
144 #endif  /* HAVE_RENAME */