[project @ 1996-07-25 20:43:49 by partain]
[ghc-hetmet.git] / ghc / lib / cbits / renameFile.lc
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1995
3 %
4 \subsection[renameFile.lc]{renameFile Runtime Support}
5
6 \begin{code}
7
8 #include "rtsdefs.h"
9 #include "stgio.h"
10
11 #ifdef HAVE_SYS_TYPES_H
12 #include <sys/types.h>
13 #endif
14
15 #ifdef HAVE_SYS_STAT_H
16 #include <sys/stat.h>
17 #endif
18
19 #ifdef HAVE_FCNTL_H
20 #include <fcntl.h>
21 #endif
22
23 StgInt
24 renameFile(opath, npath)
25 StgByteArray opath;
26 StgByteArray npath;
27 {
28     struct stat sb;
29     int fd;
30     int created = 0;
31
32     /* Check for a non-directory source */
33     while (stat(opath, &sb) != 0) {
34         if (errno != EINTR) {
35             cvtErrno();
36             stdErrno();
37             return -1;
38         }
39     }
40     if (S_ISDIR(sb.st_mode)) {
41         ghc_errtype = ERR_INAPPROPRIATETYPE;
42         ghc_errstr = "file is a directory";
43         return -1;
44     }
45
46     /* Ensure a non-directory destination */
47
48     /* First try to open without creating */
49     while ((fd = open(npath, O_RDONLY | O_NOCTTY, 0)) < 0) {
50         if (errno == ENOENT) {
51             /* Now try to create it */
52             while ((fd = open(npath, O_RDONLY | O_NOCTTY | O_CREAT | O_EXCL, 0)) < 0) {
53                 if (errno == EEXIST) {
54                     /* Race detected; go back and open without creating it */
55                     break;
56                 } else if (errno != EINTR) {
57                     cvtErrno();
58                     switch (ghc_errno) {
59                     default:
60                         stdErrno();
61                         break;
62                     case GHC_ENOENT:
63                     case GHC_ENOTDIR:
64                         ghc_errtype = ERR_NOSUCHTHING;
65                         ghc_errstr = "no path to file";
66                         break;
67                     case GHC_EINVAL:
68                         ghc_errtype = ERR_PERMISSIONDENIED;
69                         ghc_errstr = "unsupported owner or group";
70                         break;
71                     }
72                     return -1;
73                 }
74             }
75             if (fd >= 0) {
76                 created = 1;
77                 break;
78             }
79         } else if (errno != EINTR) {
80             cvtErrno();
81             switch (ghc_errno) {
82             default:
83                 stdErrno();
84                 break;
85             case GHC_ENOTDIR:
86                 ghc_errtype = ERR_NOSUCHTHING;
87                 ghc_errstr = "no path to file";
88                 break;
89             case GHC_EINVAL:
90                 ghc_errtype = ERR_PERMISSIONDENIED;
91                 ghc_errstr = "unsupported owner or group";
92                 break;
93             }
94             return -1;
95         }
96     }
97
98     /* Make sure that we aren't looking at a directory */
99
100     while (fstat(fd, &sb) < 0) {
101         /* highly unlikely */
102         if (errno != EINTR) {
103             cvtErrno();
104             if (created)
105                 (void) unlink(npath);
106             (void) close(fd);
107             return -1;
108         }
109     }
110     if (S_ISDIR(sb.st_mode)) {
111         ghc_errtype = ERR_INAPPROPRIATETYPE;
112         ghc_errstr = "destination is a directory";
113         /* We can't have created it in this case. */
114         (void) close(fd);
115         return -1;
116     }
117
118     while(rename(opath, npath) != 0) {
119         if (errno != EINTR) {
120             cvtErrno();
121             stdErrno();
122             if (created)
123                 (void) unlink(npath);
124             (void) close(fd);
125             return -1;
126         }
127     }
128
129     close(fd);    
130     return 0;
131 }
132 \end{code}