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