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