xref: /illumos-gate/usr/src/lib/libfsmgt/common/fileutil.c (revision 7a6d80f1660abd4755c68cbd094d4a914681d26e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <strings.h>
31 #include <errno.h>
32 #include <sys/types.h>
33 #include <ctype.h>
34 #include <thread.h>
35 #include <synch.h>
36 #include "libfsmgt.h"
37 
38 /*
39  * Private method declarations
40  */
41 static char *get_first_column_data(char *line);
42 static char *retrieve_string(FILE *fp, char *line, int buffersize);
43 static char *trim_trailing_whitespace(char *line);
44 
45 /*
46  * Public methods
47  */
48 
49 void
50 fileutil_free_string_array(char **arrayp, int num_elements)
51 {
52 	if (arrayp != NULL) {
53 		int	i = 0;
54 
55 		for (i = 0; i < num_elements && arrayp[i] != NULL; i++) {
56 			free(arrayp[i]);
57 		}
58 
59 		free(arrayp);
60 	}
61 } /* fileutil_free_string_array */
62 
63 char **
64 fileutil_get_first_column_data(FILE *fp, int *num_elements, int *errp)
65 {
66 	char	line[BUFSIZE];
67 	char	*returned_string;
68 	char	**return_array = NULL;
69 
70 	*errp = 0;
71 	*num_elements = 0;
72 
73 	while ((returned_string =
74 		retrieve_string(fp, line, BUFSIZE)) != NULL) {
75 
76 		char	**tmp_array;
77 
78 		tmp_array = realloc(return_array,
79 			(size_t)(((*num_elements) + 1) * sizeof (char *)));
80 		if (tmp_array == NULL) {
81 			*errp = errno;
82 			fileutil_free_string_array(return_array, *num_elements);
83 			*num_elements = 0;
84 			return (NULL);
85 		}
86 		return_array = tmp_array;
87 
88 		return_array[(*num_elements)] = strdup(returned_string);
89 		if (return_array[(*num_elements)] == NULL) {
90 			*errp = ENOMEM;
91 			fileutil_free_string_array(return_array, *num_elements);
92 			free(returned_string);
93 			*num_elements = 0;
94 			return (NULL);
95 		}
96 
97 		free(returned_string);
98 		*num_elements = *num_elements + 1;
99 	}
100 
101 	/*
102 	 * Caller must free the space allocated to return_array by calling
103 	 * fileutil_free_string_array.
104 	 */
105 	return (return_array);
106 } /* fileutil_get_first_column_data */
107 
108 /*
109  * Convenience function for retrieving the default fstype from /etc/fstypes.
110  */
111 char *
112 fileutil_getfs(FILE *fp)
113 {
114 	char *s;
115 	static char buff[BUFSIZE];	/* line buffer */
116 
117 	while (s = fgets(buff, BUFSIZE, fp)) {
118 		while (isspace(*s) || *s != '\0') /* skip leading whitespace */
119 			++s;
120 		if (*s != '#') {	/* not a comment */
121 			char *t = s;
122 			while (!isspace(*t) && *t != '\0') /* get the token */
123 				++t;
124 			*t = '\0';	/* ignore rest of line */
125 			return (s);
126 		}
127 	}
128 	return (NULL);  /* that's all, folks! */
129 } /* fileutil_getfs */
130 
131 char *
132 fileutil_getline(FILE *fp, char *line, int linesz)
133 {
134 	char *share_cmd, *p = line;
135 	*p = '\0';
136 
137 	while (fgets(line, linesz, fp) != NULL) {
138 		share_cmd = fileutil_get_cmd_from_string(line);
139 		if (share_cmd != NULL)
140 			return (share_cmd);
141 	}
142 	return (NULL);
143 } /* fileutil_getline */
144 
145 /*
146  * fileutil_get_cmd_from_string - retieves the command string minus any
147  * comments from the original string.
148  *
149  * Parameters:
150  * char *input_string - the original string.
151  */
152 char *
153 fileutil_get_cmd_from_string(char *input_stringp)
154 {
155 	/*
156 	 * Comments begin with '#'.  Strip them off.
157 	 */
158 
159 	char *returned_stringp;
160 	char *start_of_commentp;
161 	char *current_string;
162 
163 	if ((input_stringp == NULL) || (strlen(input_stringp) == 0)) {
164 		return (NULL);
165 	}
166 
167 	current_string = strdup(input_stringp);
168 
169 	if (current_string == NULL) {
170 		return (NULL);
171 	}
172 
173 	start_of_commentp = strchr(current_string, '#');
174 	if (start_of_commentp != NULL) {
175 		*start_of_commentp = '\0';
176 	}
177 
178 	returned_stringp = trim_trailing_whitespace(current_string);
179 	free(current_string);
180 	return (returned_stringp);
181 }
182 
183 /*
184  * NOTE: the caller of this function is responsible for freeing any
185  * memory allocated by calling fileutil_free_string_array()
186  *
187  * fileutil_add_string_to_array - adds one line to the file image
188  *                                   string array
189  * Parameters:
190  * char ***string_array - reference to the string array
191  * char *line - the line to be added to the temporary dfstab
192  * int *count - the number of elements in the string array
193  * int *err - error pointer for returning any errors encountered
194  *
195  * Returns:
196  * B_TRUE on success, B_FALSE on failure.
197  */
198 boolean_t
199 fileutil_add_string_to_array(char ***string_array, char *line, int *count,
200 	int *err)
201 {
202 	int i;
203 	char **ret_val = NULL;
204 	char **temp_array = NULL;
205 
206 	temp_array = *string_array;
207 
208 	ret_val = calloc(((*count) + 1), sizeof (char *));
209 	if (ret_val != NULL) {
210 		for (i = 0; i < *count; i ++) {
211 			ret_val[i] = temp_array[i];
212 		}
213 		ret_val[*count] = strdup(line);
214 		if (ret_val[*count] != NULL) {
215 			(*count)++;
216 			if (temp_array != NULL) {
217 				free(temp_array);
218 			}
219 			*string_array = ret_val;
220 		} else {
221 			*err = ENOMEM;
222 			free(ret_val);
223 			return (B_FALSE);
224 		}
225 	} else {
226 		*err = ENOMEM;
227 		return (B_FALSE);
228 	}
229 	return (B_TRUE);
230 } /* fileutil_add_string_to_array */
231 
232 /*
233  * Private methods
234  */
235 static char *
236 get_first_column_data(char *line)
237 {
238 	return (strtok(line, "\t "));
239 } /* get_first_column_data */
240 
241 static char *
242 retrieve_string(FILE *fp, char *line, int buffersize)
243 {
244 	char    *data;
245 	char	*returned_string;
246 
247 	while ((returned_string =
248 		fileutil_getline(fp, line, buffersize)) != NULL) {
249 
250 		data = get_first_column_data(returned_string);
251 		if (data != NULL)
252 			return (data);
253 	}
254 
255 	return (NULL);
256 } /* retrieve_string */
257 
258 /*
259  * trim_trailing_whitespace - helper function to remove trailing
260  * whitespace from a line
261  *
262  * Parameters:
263  * char *input_stringp - the line to be trimed
264  */
265 static char *
266 trim_trailing_whitespace(char *input_string)
267 {
268 	char *last_nonspace;
269 	char *return_string;
270 	int string_length;
271 
272 
273 	if (input_string == NULL) {
274 		return (NULL);
275 	}
276 	string_length = strlen(input_string);
277 
278 	if (string_length == 0 || *input_string == '\n') {
279 		return (NULL);
280 	}
281 
282 	return_string = strdup(input_string);
283 	if (return_string == NULL) {
284 		return (NULL);
285 	}
286 
287 	/*
288 	 * Truncates the last character which will always be '\0'
289 	 */
290 	last_nonspace = return_string + (string_length - 1);
291 
292 	while (isspace(*last_nonspace)) {
293 		last_nonspace--;
294 	}
295 	*(last_nonspace + 1) = '\0';
296 	return (return_string);
297 }
298