+++ /dev/null
-/* Utilities for reading/writing fstab, mtab, etc.
- *
- * SPDX-License-Identifier: LGPL-2.1+
- *
- */
-
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE 1
-#endif
-#include <errno.h>
-#include <mntent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "../lxc/macro.h"
-
-/* Since the values in a line are separated by spaces, a name cannot
- * contain a space. Therefore some programs encode spaces in names
- * by the strings "\040". We undo the encoding when reading an entry.
- * The decoding happens in place.
- */
-static char *decode_name(char *buf)
-{
- char *rp = buf;
- char *wp = buf;
-
- do {
- if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '4' &&
- rp[3] == '0') {
- /* \040 is a SPACE. */
- *wp++ = ' ';
- rp += 3;
- } else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' &&
- rp[3] == '1') {
- /* \011 is a TAB. */
- *wp++ = '\t';
- rp += 3;
- } else if (rp[0] == '\\' && rp[1] == '0' && rp[2] == '1' &&
- rp[3] == '2') {
- /* \012 is a NEWLINE. */
- *wp++ = '\n';
- rp += 3;
- } else if (rp[0] == '\\' && rp[1] == '\\') {
- /* We have to escape \\ to be able to represent all characters. */
- *wp++ = '\\';
- rp += 1;
- } else if (rp[0] == '\\' && rp[1] == '1' && rp[2] == '3' &&
- rp[3] == '4') {
- /* \134 is also \\. */
- *wp++ = '\\';
- rp += 3;
- } else {
- *wp++ = *rp;
- }
- } while (*rp++ != '\0');
-
- return buf;
-}
-
-/* Read one mount table entry from STREAM. Returns a pointer to storage
- * reused on the next call, or null for EOF or error (use feof/ferror to check).
- */
-struct mntent *getmntent_r(FILE *stream, struct mntent *mp, char *buffer, int bufsiz)
-{
- char *cp;
- char *head;
-
- do {
- char *end_ptr;
-
- if (!fgets(buffer, bufsiz, stream))
- return NULL;
-
- end_ptr = strchr(buffer, '\n');
- if (end_ptr != NULL) {
- /* chop newline */
- *end_ptr = '\0';
- } else {
- /* Not the whole line was read. Do it now but forget it. */
- char tmp[1024] = {0};
-
- while (fgets(tmp, sizeof tmp, stream))
- if (strchr(tmp, '\n') != NULL)
- break;
- }
-
- head = buffer + strspn(buffer, " \t");
- /* skip empty lines and comment lines: */
- } while (head[0] == '\0' || head[0] == '#');
-
- cp = strsep(&head, " \t");
- mp->mnt_fsname = cp ? decode_name(cp) : (char *)"";
- if (head)
- head += strspn(head, " \t");
-
- cp = strsep(&head, " \t");
- mp->mnt_dir = cp ? decode_name(cp) : (char *)"";
- if (head)
- head += strspn(head, " \t");
-
- cp = strsep(&head, " \t");
- mp->mnt_type = cp ? decode_name(cp) : (char *)"";
- if (head)
- head += strspn(head, " \t");
-
- cp = strsep(&head, " \t");
- mp->mnt_opts = cp ? decode_name(cp) : (char *)"";
- if (head) {
- int ret = sscanf(head, " %d %d ", &mp->mnt_freq, &mp->mnt_passno);
-
- switch (ret) {
- case 0:
- mp->mnt_freq = 0;
- break;
- case 1:
- mp->mnt_passno = 0;
- break;
- case 2:
- break;
- }
- } else {
- mp->mnt_freq = 0;
- }
-
- return mp;
-}
-
-struct mntent *getmntent(FILE *stream)
-{
- static struct mntent m;
- static char *getmntent_buffer;
-
- if (!getmntent_buffer) {
- getmntent_buffer = (char *)malloc(LXC_MAX_BUFFER);
- if (!getmntent_buffer)
- return NULL;
- }
-
- return getmntent_r(stream, &m, getmntent_buffer, LXC_MAX_BUFFER);
-}
-
-/* Prepare to begin reading and/or writing mount table entries from the
- * beginning of FILE. MODE is as for `fopen'.
- */
-FILE *setmntent(const char *file, const char *mode)
-{
- /* Extend the mode parameter with "c" to disable cancellation in the
- * I/O functions and "e" to set FD_CLOEXEC.
- */
- size_t modelen = strlen(mode);
- char newmode[256];
-
- if (modelen >= (sizeof(newmode) - 3)) {
- errno = -EFBIG;
- return NULL;
- }
-
- memcpy(newmode, mode, modelen);
- memcpy(newmode + modelen, "ce", 3);
-
- return fopen(file, newmode);
-}
-
-/* Close a stream opened with `setmntent'. */
-int endmntent(FILE *stream)
-{
- /* SunOS 4.x allows for NULL stream */
- if (stream)
- fclose(stream);
-
- /* SunOS 4.x says to always return 1 */
- return 1;
-}
-
-/* Search MNT->mnt_opts for an option matching OPT.
- * Returns the address of the substring, or null if none found.
- */
-char *hasmntopt(const struct mntent *mnt, const char *opt)
-{
- const size_t optlen = strlen(opt);
- char *rest = mnt->mnt_opts, *p;
-
- while ((p = strstr(rest, opt))) {
- if ((p == rest || p[-1] == ',') &&
- (p[optlen] == '\0' || p[optlen] == '=' || p[optlen] == ','))
- return p;
-
- rest = strchr(p, ',');
- if (!rest)
- break;
-
- ++rest;
- }
-
- return NULL;
-}