/src/include/lxcmntent.c

https://gitlab.com/Red54/lxc · C · 193 lines · 130 code · 23 blank · 40 comment · 79 complexity · 0b1fa9c168b2c4f13f26d8144284893d MD5 · raw file

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