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