blob: 939ce208a07d73d54edfd559330a4770ef634abf [file] [log] [blame]
xf.liaa4d92f2023-09-13 00:18:58 -07001/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9#include <stdio.h>
10#include <stdlib.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <errno.h>
15#include <unistd.h>
16
17#define FAST_FUNC
18
19ssize_t FAST_FUNC safe_read(int fd, void *buf, size_t count)
20{
21 ssize_t n;
22
23 for (;;) {
24 n = read(fd, buf, count);
25 if (n >= 0 || errno != EINTR)
26 break;
27 /* Some callers set errno=0, are upset when they see EINTR.
28 * Returning EINTR is wrong since we retry read(),
29 * the "error" was transient.
30 */
31 errno = 0;
32 /* repeat the read() */
33 }
34
35 return n;
36}
37
38/*
39 * Read all of the supplied buffer from a file.
40 * This does multiple reads as necessary.
41 * Returns the amount read, or -1 on an error.
42 * A short read is returned on an end of file.
43 */
44ssize_t FAST_FUNC full_read(int fd, void *buf, size_t len)
45{
46 ssize_t cc;
47 ssize_t total;
48
49 total = 0;
50
51 while (len) {
52 cc = safe_read(fd, buf, len);
53
54 if (cc < 0) {
55 if (total) {
56 /* we already have some! */
57 /* user can do another read to know the error code */
58 return total;
59 }
60 return cc; /* read() returns -1 on failure. */
61 }
62 if (cc == 0)
63 break;
64 buf = ((char *)buf) + cc;
65 total += cc;
66 len -= cc;
67 }
68
69 return total;
70}
71
72ssize_t FAST_FUNC read_close(int fd, void *buf, size_t size)
73{
74 /*int e;*/
75 size = full_read(fd, buf, size);
76 /*e = errno;*/
77 close(fd);
78 /*errno = e;*/
79 return size;
80}
81
82ssize_t FAST_FUNC open_read_close(const char *filename, void *buf, size_t size)
83{
84#ifdef ZXIC_WIN
85 int fd = open(filename, O_RDONLY | O_BINARY);
86#else
87 int fd = open(filename, O_RDONLY);
88#endif
89 if (fd < 0)
90 return fd;
91 return read_close(fd, buf, size);
92}
93
94ssize_t FAST_FUNC safe_write(int fd, const void *buf, size_t count)
95{
96 ssize_t n;
97
98 for (;;) {
99 n = write(fd, buf, count);
100 if (n >= 0 || errno != EINTR)
101 break;
102 /* Some callers set errno=0, are upset when they see EINTR.
103 * Returning EINTR is wrong since we retry write(),
104 * the "error" was transient.
105 */
106 errno = 0;
107 /* repeat the write() */
108 }
109
110 return n;
111}
112
113ssize_t FAST_FUNC full_write(int fd, const void *buf, size_t len)
114{
115 ssize_t cc;
116 ssize_t total;
117
118 total = 0;
119
120 while (len) {
121 cc = safe_write(fd, buf, len);
122
123 if (cc < 0) {
124 if (total) {
125 /* we already wrote some! */
126 /* user can do another write to know the error code */
127 return total;
128 }
129 return cc; /* write() returns -1 on failure. */
130 }
131
132 total += cc;
133 buf = ((const char *)buf) + cc;
134 len -= cc;
135 }
136
137 return total;
138}
139
140ssize_t FAST_FUNC open_write_close(const char *filename, void *buf, size_t size)
141{
142 ssize_t ret;
143#ifdef ZXIC_WIN
144 int fd_to = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, 0640);
145#else
146 int fd_to = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_SYNC, 0640);
147#endif
148
149 if(fd_to < 0)
150 return -1;
151
152 ret = full_write(fd_to, buf, size);
153 fsync(fd_to);
154 close(fd_to);
155
156 return ret;
157}