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