1 /* Copyright (C) 1995-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #include <fstab.h>
19 #include <mntent.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <libc-lock.h>
24 
25 #define BUFFER_SIZE 0x1fc0
26 
27 struct fstab_state
28 {
29   FILE *fs_fp;
30   char *fs_buffer;
31   struct mntent fs_mntres;
32   struct fstab fs_ret;
33 };
34 
35 static struct fstab_state *fstab_init (int opt_rewind);
36 static struct mntent *fstab_fetch (struct fstab_state *state);
37 static struct fstab *fstab_convert (struct fstab_state *state);
38 
39 static struct fstab_state fstab_state;
40 
41 
42 int
setfsent(void)43 setfsent (void)
44 {
45   return fstab_init (1) != NULL;
46 }
47 
48 
49 struct fstab *
getfsent(void)50 getfsent (void)
51 {
52   struct fstab_state *state;
53 
54   state = fstab_init (0);
55   if (state == NULL)
56     return NULL;
57   if (fstab_fetch (state) == NULL)
58     return NULL;
59   return fstab_convert (state);
60 }
61 
62 
63 struct fstab *
getfsspec(const char * name)64 getfsspec (const char *name)
65 {
66   struct fstab_state *state;
67   struct mntent *m;
68 
69   state = fstab_init (1);
70   if (state == NULL)
71     return NULL;
72   while ((m = fstab_fetch (state)) != NULL)
73     if (strcmp (m->mnt_fsname, name) == 0)
74       return fstab_convert (state);
75   return NULL;
76 }
77 
78 
79 struct fstab *
getfsfile(const char * name)80 getfsfile (const char *name)
81 {
82   struct fstab_state *state;
83   struct mntent *m;
84 
85   state = fstab_init (1);
86   if (state == NULL)
87     return NULL;
88   while ((m = fstab_fetch (state)) != NULL)
89     if (strcmp (m->mnt_dir, name) == 0)
90       return fstab_convert (state);
91   return NULL;
92 }
93 
94 
95 void
endfsent(void)96 endfsent (void)
97 {
98   struct fstab_state *state;
99 
100   state = &fstab_state;
101   if (state->fs_fp != NULL)
102     {
103       (void) __endmntent (state->fs_fp);
104       state->fs_fp = NULL;
105     }
106 }
107 
108 
109 static struct fstab_state *
fstab_init(int opt_rewind)110 fstab_init (int opt_rewind)
111 {
112   struct fstab_state *state;
113   char *buffer;
114   FILE *fp;
115 
116   state = &fstab_state;
117 
118   buffer = state->fs_buffer;
119   if (buffer == NULL)
120     {
121       buffer = (char *) malloc (BUFFER_SIZE);
122       if (buffer == NULL)
123 	return NULL;
124       state->fs_buffer = buffer;
125     }
126 
127   fp = state->fs_fp;
128   if (fp != NULL)
129     {
130       if (opt_rewind)
131 	rewind (fp);
132     }
133   else
134     {
135       fp = __setmntent (_PATH_FSTAB, "r");
136       if (fp == NULL)
137 	return NULL;
138       state->fs_fp = fp;
139     }
140 
141   return state;
142 }
143 
144 
145 static struct mntent *
fstab_fetch(struct fstab_state * state)146 fstab_fetch (struct fstab_state *state)
147 {
148   return __getmntent_r (state->fs_fp, &state->fs_mntres,
149 			state->fs_buffer, BUFFER_SIZE);
150 }
151 
152 
153 static struct fstab *
fstab_convert(struct fstab_state * state)154 fstab_convert (struct fstab_state *state)
155 {
156   struct mntent *m;
157   struct fstab *f;
158 
159   m = &state->fs_mntres;
160   f = &state->fs_ret;
161 
162   f->fs_spec = m->mnt_fsname;
163   f->fs_file = m->mnt_dir;
164   f->fs_vfstype = m->mnt_type;
165   f->fs_mntops = m->mnt_opts;
166   f->fs_type = (__hasmntopt (m, FSTAB_RW) ? FSTAB_RW
167 		: __hasmntopt (m, FSTAB_RQ) ? FSTAB_RQ
168 		: __hasmntopt (m, FSTAB_RO) ? FSTAB_RO
169 		: __hasmntopt (m, FSTAB_SW) ? FSTAB_SW
170 		: __hasmntopt (m, FSTAB_XX) ? FSTAB_XX
171 		: "??");
172   f->fs_freq = m->mnt_freq;
173   f->fs_passno = m->mnt_passno;
174   return f;
175 }
176 
177 
178 /* Make sure the memory is freed if the programs ends while in
179    memory-debugging mode and something actually was allocated.  */
libc_freeres_fn(fstab_free)180 libc_freeres_fn (fstab_free)
181 {
182   char *buffer;
183 
184   buffer = fstab_state.fs_buffer;
185   free ((void *) buffer);
186 }
187