1 /* vu-utils.c - vu helper functions
2 *
3 ****************************************************************
4 * Copyright (C) 2000 Thomas Lord
5 *
6 * See the file "COPYING" for further information about
7 * the copyright and warranty status of this work.
8 */
9
10
11
12 #include "hackerlab/os/errno.h"
13 #include "hackerlab/mem/must-malloc.h"
14 #include "hackerlab/char/str.h"
15 #include "hackerlab/vu/vu-utils.h"
16
17
18 /************************************************************************
19 *(h0 "VU Utilities")
20 *
21 * These functions provide higher-level abstractions that capture common
22 * ways of using the lower-level VU functions.
23 */
24
25
26
27 /*(c vu_file_to_string)
28 * int vu_file_to_string (int * errn,
29 * t_uchar ** buf,
30 * size_t * len,
31 * int fd);
32 *
33 * Read the entire contents of `fd' into a newly allocated string.
34 *
35 * If no error occurs, return 0. The new string is returned in `*buf';
36 * its length in `*len'.
37 *
38 * If an I/O error occurs, return -1 and fill `*errn'.
39 *
40 * If `vu_fstat' is able to report the length of the file, a single call to
41 * `vu_read_retry' is used to read its contents. Otherwise, repeated calls
42 * to `vu_read_retry' are used.
43 */
44 int
vu_file_to_string(int * errn,t_uchar ** buf,size_t * len,int fd)45 vu_file_to_string (int * errn,
46 t_uchar ** buf,
47 size_t * len,
48 int fd)
49 {
50 struct stat sb;
51
52 if (!vu_fstat (errn, fd, &sb))
53 {
54 *buf = (t_uchar *)must_malloc (sb.st_size);
55
56 if (sb.st_size != vu_read_retry (errn, fd, *buf, sb.st_size))
57 {
58 must_free (*buf);
59 return -1;
60 }
61
62 *len = sb.st_size;
63 return 0;
64 }
65 else
66 {
67 #define chunk 8192
68 size_t total;
69
70 *buf = (t_uchar *)must_malloc (chunk);
71 total = 0;
72
73 while (1)
74 {
75 ssize_t amt;
76
77 amt = vu_read_retry (errn, fd, *buf + total, chunk);
78 if (amt < 0)
79 {
80 must_free (*buf);
81 return -1;
82 }
83 if (amt == 0)
84 {
85 *buf = (t_uchar *)must_realloc ((void *)*buf, total);
86 *len = total;
87 return 0;
88 }
89 total += amt;
90 *buf = (t_uchar *)must_realloc ((void *)*buf, total + chunk);
91 }
92 }
93 }
94
95
96
97
98 /*(c vu_move_fd)
99 * int vu_move_fd (int * errn, int fd, int newfd);
100 *
101 * Relocate `fd' to `newfd'. `fd' must already be handled by VU.
102 *
103 * Thus function performs a `vu_dup' or `vu_dup2'
104 *
105 * This is useful when performing file redirections after `fork' and
106 * before `exec'.
107 *
108 */
109 int
vu_move_fd(int * errn,int fd,int newfd)110 vu_move_fd (int * errn, int fd, int newfd)
111 {
112 int ign;
113
114 if (fd < 0)
115 {
116 if (errn) *errn = EINVAL;
117 return -1;
118 }
119 if (fd == newfd)
120 return 0;
121
122 if (newfd == -1)
123 newfd = vu_dup (errn, fd);
124 else
125 newfd = vu_dup2 (errn, fd, newfd);
126
127 if (newfd < 0)
128 return -1;
129
130 if (0 > vu_move_state (errn, fd, newfd))
131 {
132 vu_close (&ign, newfd);
133 return -1;
134 }
135
136 vu_close (&ign, fd);
137 return newfd;
138 }
139
140
141
142
143 /*(c vu_file_is_directory)
144 * int vu_file_is_directory (int * errn, const t_uchar * name);
145 *
146 * Return 1 if `name' names a directory, 0 if not, -1 on error.
147 *
148 * Non-existence of any file called `name' is not an error.
149 */
150 int
vu_file_is_directory(int * errn,const t_uchar * name)151 vu_file_is_directory (int * errn, const t_uchar * name)
152 {
153 int e;
154 struct stat sb;
155
156 if (0 > vu_lstat (&e, name, &sb))
157 {
158 if (e == ENOENT)
159 return 0;
160 if (errn) *errn = e;
161 return -1;
162 }
163
164 return (S_ISDIR (sb.st_mode));
165 }
166
167
168 /*(c vu_file_is_directory_following)
169 * int vu_file_is_directory_following (int * errn, const t_uchar * name);
170 *
171 * Return 1 if `name' names a directory or symlink to a directory,
172 * 0 if not, -1 on error.
173 *
174 * Non-existence of any file called `name' is not an error.
175 */
176 int
vu_file_is_directory_following(int * errn,const t_uchar * name)177 vu_file_is_directory_following (int * errn, const t_uchar * name)
178 {
179 int e;
180 struct stat sb;
181
182 if (0 > vu_stat (&e, name, &sb))
183 {
184 if (e == ENOENT)
185 return 0;
186 if (errn) *errn = e;
187 return -1;
188 }
189
190 return (S_ISDIR (sb.st_mode));
191 }
192