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