1  /* Copyright (C) 1995-2023 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
      43  setfsent (void)
      44  {
      45    return fstab_init (1) != NULL;
      46  }
      47  
      48  
      49  struct fstab *
      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 *
      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 *
      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
      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 *
     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 *
     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 *
     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.  */
     180  void
     181  __libc_fstab_freemem (void)
     182  {
     183    char *buffer;
     184  
     185    buffer = fstab_state.fs_buffer;
     186    free ((void *) buffer);
     187  }