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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 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/*
30 * Traverses /etc/dfs/sharetab in order to find shared file systems
31 */
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <strings.h>
36#include <errno.h>
37#include <thread.h>
38#include <synch.h>
39#include "libfsmgt.h"
40#include <sharefs/share.h>
41#include "sharetab.h"
42
43#define	SECMODES 5
44
45/*
46 * Private variables
47 */
48static mutex_t	sharetab_lock = DEFAULTMUTEX;
49
50/*
51 * Private method declarations
52 */
53fs_sharelist_t	*create_sharelist_entry(struct share *sharetab_entry,
54					int *errp);
55
56/*
57 * Public methods
58 */
59
60void
61fs_free_share_list(fs_sharelist_t *headp)
62{
63	fs_sharelist_t	*tmp;
64
65	while (headp != NULL) {
66		tmp = headp->next;
67		free(headp->path);
68		free(headp->resource);
69		free(headp->fstype);
70		free(headp->options);
71		free(headp->description);
72		headp->next = NULL;
73		free(headp);
74
75		headp = tmp;
76	}
77}
78
79/*
80 * Get a linked list of all the shares on the system from /etc/dfs/dfstab
81 */
82fs_sharelist_t *
83fs_get_share_list(int *errp)
84{
85	fs_sharelist_t	*newp;
86	fs_sharelist_t	*headp;
87	fs_sharelist_t	*tailp;
88	FILE		*fp;
89
90	headp = NULL;
91	tailp = NULL;
92
93	if ((fp = fopen(SHARETAB, "r")) != NULL) {
94		struct share	*sharetab_entry;
95
96		(void) mutex_lock(&sharetab_lock);
97		while (getshare(fp, &sharetab_entry) > 0) {
98
99			newp = create_sharelist_entry(sharetab_entry, errp);
100			if (newp == NULL) {
101				/*
102				 * Out of memory
103				 */
104				fs_free_share_list(headp);
105				(void) mutex_unlock(&sharetab_lock);
106				(void) fclose(fp);
107				return (NULL);
108			}
109
110			if (headp == NULL) {
111				headp = newp;
112				tailp = newp;
113			} else {
114				tailp->next = newp;
115				tailp = newp;
116			}
117
118		} /* while (getshare(fp, &sharetab_entry) != 0) */
119		(void) mutex_unlock(&sharetab_lock);
120		(void) fclose(fp);
121	} else {
122		*errp = errno;
123	} /* if ((fp = fopen(SHARETAB, "r")) != NULL) */
124
125	/*
126	 * Caller must free the mount list
127	 */
128	return (headp);
129} /* fs_get_share_list */
130
131
132/*
133 * fs_parse_opts_for_sec_modes
134 * Get an array of strings of all the security modes of the option string.
135 *
136 * char *cmd - The option string from the share command.
137 * int *count - pointer to the number of elements in the returned array.
138 * int *error - error pointer for returning any errors.
139 */
140char **
141fs_parse_opts_for_sec_modes(char *cmd, int *count, int *error)
142{
143	char *temp_str;
144	char **secstringarray;
145	char *strptr;
146
147	*count = 0;
148	strptr = strdup(cmd);
149	if (strptr == NULL) {
150		*error = ENOMEM;
151		return (NULL);
152	}
153
154	temp_str = strptr;
155
156	secstringarray =
157	    (char **)calloc((size_t)SECMODES, (size_t)(sizeof (char *)));
158	if (secstringarray == NULL) {
159		*error = ENOMEM;
160		return (NULL);
161	}
162
163	if (strstr(strptr, "sec=") != NULL) {
164		char *next_str;
165		next_str = strptr;
166
167		while (next_str != NULL) {
168			next_str = strstr(strptr, "sec=");
169			if (next_str != NULL) {
170				if (strncmp(strptr, "sec=", 4) != 0) {
171					*(next_str - 1) = '\0';
172				}
173				strptr = next_str;
174				next_str = strstr(strptr + 4, "sec=");
175				if (next_str != NULL) {
176					*(next_str - 1) = '\0';
177				}
178				secstringarray[*count] = strdup(strptr);
179				if (secstringarray[*count] == NULL) {
180					*error = ENOMEM;
181					if (*count > 0) {
182						fileutil_free_string_array(
183						    secstringarray, *count);
184					} else {
185						free(secstringarray);
186					}
187					free(temp_str);
188					return (NULL);
189				}
190				strptr = next_str;
191				(*count)++;
192			}
193		}
194	} else {
195		secstringarray[*count] = strdup(temp_str);
196		if (secstringarray[*count] == NULL) {
197			*error = ENOMEM;
198			if (*count > 0) {
199				fileutil_free_string_array(
200				    secstringarray, *count);
201			} else {
202				free(secstringarray);
203			}
204			free(temp_str);
205			return (NULL);
206		}
207		(*count)++;
208	}
209	free(temp_str);
210	return (secstringarray);
211}
212
213/*
214 * fs_create_array_from_accesslist
215 * Takes the colon seperated access list parses the list into an array
216 * containing all the elements of the list. The array created is returned
217 * and count is set to the number of elements in the array.
218 *
219 * char *access_list - The string containing the colon sperated access list.
220 * int *count - Will contain the number of elements in the array.
221 * int *err - any errors encountered.
222 */
223char **
224fs_create_array_from_accesslist(char *access_list, int *count, int *err)
225{
226	char *delimiter = ":";
227	char *server_string;
228	char **list_array = NULL;
229	char *list_copy;
230
231	*count = 0;
232	if (access_list != NULL) {
233		list_copy = strdup(access_list);
234		if (list_copy != NULL) {
235			server_string = strtok(list_copy, delimiter);
236			if (server_string != NULL) {
237				while (server_string != NULL) {
238					if (!fileutil_add_string_to_array(
239					    &list_array, server_string, count,
240					    err)) {
241						fileutil_free_string_array(
242						    list_array, *count);
243						free(list_copy);
244						goto return_err;
245					}
246					server_string =
247					    strtok(NULL, delimiter);
248				}
249			} else {
250				list_array =
251				    (char **)calloc(((*count) + 1),
252				    sizeof (char *));
253				if (list_array == NULL) {
254					*err = ENOMEM;
255					free(list_copy);
256					goto return_err;
257				}
258				list_array[*count] = strdup(access_list);
259				if (list_array[*count] == NULL) {
260					*err = ENOMEM;
261					free(list_array);
262					list_array = NULL;
263					goto return_err;
264				}
265				(*count)++;
266			}
267			free(list_copy);
268		} else {
269			*err = ENOMEM;
270		}
271	}
272return_err:
273	return (list_array);
274} /* fs_create_array_from_accesslist */
275
276
277/*
278 * Private Methods
279 */
280
281fs_sharelist_t *
282create_sharelist_entry(struct share *sharetab_entry, int *errp)
283{
284
285	fs_sharelist_t	*newp;
286
287	newp = (fs_sharelist_t *)calloc((size_t)1,
288	    (size_t)sizeof (fs_sharelist_t));
289
290	if (newp == NULL) {
291		/*
292		 * Out of memory
293		 */
294		*errp = errno;
295		return (NULL);
296	}
297
298	newp->path = strdup(sharetab_entry->sh_path);
299	if (newp->path == NULL) {
300		/*
301		 * Out of memory
302		 */
303		*errp = errno;
304		fs_free_share_list(newp);
305		return (NULL);
306	}
307
308	newp->resource = strdup(sharetab_entry->sh_res);
309	if (newp->path == NULL) {
310		/*
311		 * Out of memory
312		 */
313		*errp = errno;
314		fs_free_share_list(newp);
315		return (NULL);
316	}
317
318	newp->fstype = strdup(sharetab_entry->sh_fstype);
319	if (newp->fstype == NULL) {
320		/*
321		 * Out of memory
322		 */
323		*errp = errno;
324		fs_free_share_list(newp);
325		return (NULL);
326	}
327
328	newp->options = strdup(sharetab_entry->sh_opts);
329	if (newp->options == NULL) {
330		/*
331		 * Out of memory
332		 */
333		*errp = errno;
334		fs_free_share_list(newp);
335		return (NULL);
336	}
337
338	newp->description = strdup(sharetab_entry->sh_descr);
339	if (newp->description == NULL) {
340		/*
341		 * Out of memory
342		 */
343		*errp = errno;
344		fs_free_share_list(newp);
345		return (NULL);
346	}
347	newp->next = NULL;
348
349	return (newp);
350} /* create_sharelist_entry */
351