]> git.proxmox.com Git - mirror_lxc.git/blame - src/include/lxcmntent.c
tests: remove VLAs
[mirror_lxc.git] / src / include / lxcmntent.c
CommitLineData
250b1eec
SG
1/* Utilities for reading/writing fstab, mtab, etc.
2 Copyright (C) 1995-2000, 2001, 2002, 2003, 2006
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
edaf8b1b
SG
21#include <stdio.h>
22#include <string.h>
23#include <mntent.h>
24
25/* Since the values in a line are separated by spaces, a name cannot
26 contain a space. Therefore some programs encode spaces in names
27 by the strings "\040". We undo the encoding when reading an entry.
28 The decoding happens in place. */
29static char *
30decode_name (char *buf)
31{
32 char *rp = buf;
33 char *wp = buf;
34
35 do
36 if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' && rp[3] == '0')
37 {
38 /* \040 is a SPACE. */
39 *wp++ = ' ';
40 rp += 3;
41 }
42 else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '1')
43 {
44 /* \011 is a TAB. */
45 *wp++ = '\t';
46 rp += 3;
47 }
48 else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' && rp[3] == '2')
49 {
50 /* \012 is a NEWLINE. */
51 *wp++ = '\n';
52 rp += 3;
53 }
54 else if (rp[0] == '\\' && rp[1] == '\\')
55 {
56 /* We have to escape \\ to be able to represent all characters. */
57 *wp++ = '\\';
58 rp += 1;
59 }
60 else if (rp[0] == '\\' && rp[1] == '1' && rp[2] == '3' && rp[3] == '4')
61 {
62 /* \134 is also \\. */
63 *wp++ = '\\';
64 rp += 3;
65 }
66 else
67 *wp++ = *rp;
68 while (*rp++ != '\0');
69
70 return buf;
71}
72
73/* Read one mount table entry from STREAM. Returns a pointer to storage
74 reused on the next call, or null for EOF or error (use feof/ferror to
75 check). */
76struct mntent *getmntent_r (FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
77{
78 char *cp;
79 char *head;
80
81 do
82 {
83 char *end_ptr;
84
85 if (fgets (buffer, bufsiz, stream) == NULL)
86 {
87 return NULL;
88 }
89
90 end_ptr = strchr (buffer, '\n');
91 if (end_ptr != NULL) /* chop newline */
92 *end_ptr = '\0';
93 else
94 {
95 /* Not the whole line was read. Do it now but forget it. */
96 char tmp[1024];
97 while (fgets (tmp, sizeof tmp, stream) != NULL)
98 if (strchr (tmp, '\n') != NULL)
99 break;
100 }
101
102 head = buffer + strspn (buffer, " \t");
103 /* skip empty lines and comment lines: */
104 }
105 while (head[0] == '\0' || head[0] == '#');
106
107 cp = strsep (&head, " \t");
108 mp->mnt_fsname = cp != NULL ? decode_name (cp) : (char *) "";
109 if (head)
110 head += strspn (head, " \t");
111 cp = strsep (&head, " \t");
112 mp->mnt_dir = cp != NULL ? decode_name (cp) : (char *) "";
113 if (head)
114 head += strspn (head, " \t");
115 cp = strsep (&head, " \t");
116 mp->mnt_type = cp != NULL ? decode_name (cp) : (char *) "";
117 if (head)
118 head += strspn (head, " \t");
119 cp = strsep (&head, " \t");
120 mp->mnt_opts = cp != NULL ? decode_name (cp) : (char *) "";
121 switch (head ? sscanf (head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno) : 0)
122 {
123 case 0:
124 mp->mnt_freq = 0;
125 case 1:
126 mp->mnt_passno = 0;
127 case 2:
128 break;
129 }
130
131 return mp;
132}
133
134struct mntent *getmntent (FILE *stream)
135{
136 static struct mntent m;
137 static char *getmntent_buffer;
138
139 #define BUFFER_SIZE 4096
140 if (getmntent_buffer == NULL) {
141 getmntent_buffer = (char *) malloc (BUFFER_SIZE);
142 }
143
144 return getmntent_r (stream, &m, getmntent_buffer, BUFFER_SIZE);
145 #undef BUFFER_SIZE
146}
147
148
149/* Prepare to begin reading and/or writing mount table entries from the
150 beginning of FILE. MODE is as for `fopen'. */
151FILE *setmntent (const char *file, const char *mode)
152{
153 /* Extend the mode parameter with "c" to disable cancellation in the
154 I/O functions and "e" to set FD_CLOEXEC. */
155 size_t modelen = strlen (mode);
156 char newmode[modelen + 3];
157 memcpy (newmode, mode, modelen);
158 memcpy (newmode + modelen, "ce", 3);
159 FILE *result = fopen (file, newmode);
160
161 return result;
162}
163
164
165/* Close a stream opened with `setmntent'. */
166int endmntent (FILE *stream)
167{
168 if (stream) /* SunOS 4.x allows for NULL stream */
169 fclose (stream);
170 return 1; /* SunOS 4.x says to always return 1 */
171}
172
173/* Search MNT->mnt_opts for an option matching OPT.
174 Returns the address of the substring, or null if none found. */
175char *hasmntopt (const struct mntent *mnt, const char *opt)
176{
177 const size_t optlen = strlen (opt);
178 char *rest = mnt->mnt_opts, *p;
179
180 while ((p = strstr (rest, opt)) != NULL)
181 {
182 if ((p == rest || p[-1] == ',')
183 && (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
184 return p;
185
186 rest = strchr (p, ',');
187 if (rest == NULL)
188 break;
189 ++rest;
190 }
191
192 return NULL;
193}