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