revert-ubik-changes-20080405
[openafs.git] / src / util / fileutil.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* File-oriented utility functions */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 RCSID
16     ("$Header$");
17
18 #include <afs/stds.h>
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <errno.h>
23 #include <string.h>
24
25 #ifdef AFS_NT40_ENV
26 #include <windows.h>
27 #include <io.h>
28 #include "errmap_nt.h"
29 #endif
30
31 #ifdef HAVE_UNISTD_H
32 #include <unistd.h>
33 #endif
34 #include <sys/types.h>
35 #include <dirent.h>
36 #include <sys/stat.h>
37 #ifdef HAVE_FCNTL_H
38 #include <fcntl.h>
39 #endif
40 #include "fileutil.h"
41
42
43 /*
44  * renamefile() -- rename a file (Unix rename() semantics)
45  */
46 int
47 renamefile(const char *oldname, const char *newname)
48 {
49     int rc = 0;
50
51 #ifdef AFS_NT40_ENV
52     if (!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING)) {
53         /* rename failed */
54         errno = nterr_nt2unix(GetLastError(), EIO);
55         rc = -1;
56     }
57 #else
58     rc = rename(oldname, newname);
59 #endif
60     return rc;
61 }
62
63
64 /*
65  * FilepathNormalizeEx() -- normalize file path; i.e., use only forward (or only 
66  *     backward) slashes, remove multiple and trailing slashes.
67  */
68 void
69 FilepathNormalizeEx(char *path, int slashType)
70 {
71     short bWasSlash = 0;
72     char *pP, *pCopyFrom;
73     char slash = '/';           /* Default to forward slashes */
74
75     if (slashType == FPN_BACK_SLASHES)
76         slash = '\\';
77
78     if (path != NULL) {
79         /* use only forward slashes; remove multiple slashes */
80         for (pP = pCopyFrom = path; *pCopyFrom != '\0'; pCopyFrom++) {
81             if ((*pCopyFrom == '/') || (*pCopyFrom == '\\')) {
82                 if (!bWasSlash) {
83                     *pP++ = slash;
84                     bWasSlash = 1;
85                 }
86             } else {
87                 *pP++ = *pCopyFrom;
88                 bWasSlash = 0;
89             }
90         }
91         *pP = '\0';
92
93         /* strip off trailing slash (unless specifies root) */
94         pP--;
95         if ((*pP == slash) && (pP != path)) {
96 #ifdef AFS_NT40_ENV
97             /* check for "X:/" */
98             if (*(pP - 1) != ':') {
99                 *pP = '\0';
100             }
101 #else
102             *pP = '\0';
103 #endif
104         }
105     }
106 }
107
108
109 void
110 FilepathNormalize(char *path)
111 {
112     FilepathNormalizeEx(path, FPN_FORWARD_SLASHES);
113 }
114
115 /* Open a file for buffered I/O */
116 bufio_p
117 BufioOpen(char *path, int oflag, int mode)
118 {
119     bufio_p bp;
120
121     bp = (bufio_p) malloc(sizeof(bufio_t));
122     if (bp == NULL) {
123         return NULL;
124     }
125 #ifdef AFS_NT40_ENV
126     bp->fd = _open(path, oflag, mode);
127 #else
128     bp->fd = open(path, oflag, mode);
129 #endif
130     if (bp->fd == BUFIO_INVALID_FD) {
131         free(bp);
132         return NULL;
133     }
134
135     bp->pos = 0;
136     bp->len = 0;
137     bp->eof = 0;
138
139     return bp;
140 }
141
142 /* Read the next line of a file up to len-1 bytes into buf,
143  * and strip off the carriage return. buf is null terminated.
144  * Returns -1 on EOF or error, length of string on success.
145  */
146 int
147 BufioGets(bufio_p bp, char *buf, int buflen)
148 {
149     int rc;
150     char c;
151     int tlen, pos, len;
152
153     if (!buf || buflen <= 1 || !bp || bp->eof) {
154         return -1;
155     }
156
157     tlen = 0;
158     pos = bp->pos;
159     len = bp->len;
160     while (1) {
161         if (pos >= len) {
162 #ifdef AFS_NT40_ENV
163             rc = _read(bp->fd, bp->buf, BUFIO_BUFSIZE);
164 #else
165             rc = read(bp->fd, bp->buf, BUFIO_BUFSIZE);
166 #endif
167             if (rc < 0) {
168                 bp->eof = 1;
169                 return -1;
170             } else if (rc == 0) {
171                 bp->eof = 1;
172                 if (tlen == 0) {
173                     return -1;
174                 } else {
175                     return tlen;
176                 }
177             }
178             pos = bp->pos = 0;
179             len = bp->len = rc;
180         }
181         while (pos < len) {
182             c = bp->buf[pos++];
183             if (c == '\n') {
184                 buf[tlen] = '\0';
185                 bp->pos = pos;
186                 bp->len = len;
187                 return tlen;
188             } else {
189                 buf[tlen++] = c;
190                 if (tlen >= buflen - 1) {
191                     buf[tlen] = '\0';
192                     bp->pos = pos;
193                     bp->len = len;
194                     return tlen;
195                 }
196             }
197         }
198     }
199 }
200
201 /* Close a buffered I/O handle */
202 int
203 BufioClose(bufio_p bp)
204 {
205     BUFIO_FD fd;
206     int rc;
207
208     if (!bp) {
209         return -1;
210     }
211     fd = bp->fd;
212     free(bp);
213 #ifdef AFS_NT40_ENV
214     rc = _close(fd);
215 #else
216     rc = close(fd);
217 #endif
218
219     return rc;
220 }