/*
 * SPDX-FileCopyrightText: 2026 Didier Kryn <kryn@in2p3.fr>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
/*----------------------------------------------------------------------------*/
/*   Build a list of the disks used by partitions listed in /proc/mounts or   */
/*   /proc/self/mountinfo.                                                    */
/*                                                                            */
/*    Any partition (eg /dev/sda5)  listed in the file is considered as using */
/* the disk it is built on (in the example, /dev/sda).  Also RAID devices are */
/* considered as  using  the disks they are built from.                       */
/*                                                                            */
/*    This couldn't work to parse  /etc/fstab because, in fstab, filesystems  */
/* may be specified  by other means  than the  device file  and we would need */
/* blkid_evaluate_spec() (from libblkid)  to obtain the device file.          */
/*                                                                            */
/*    In addition to listing disks,  check if the blockdevice name  specified */
/* by argument blkname is already mounted.                                    */
/*----------------------------------------------------------------------------*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>
#include <limits.h>
#include <mntent.h>
#include <blkid/blkid.h>
#include "slash_sys.h"

size_t strLcpy(char *dst, const char *src, size_t dsize);

int lsmtab( FILE *pf, void (*add_to_list)(const char *name, size_t len),
           const char *blkname)
{
/* List of exotic filesystems types which don't use a real device */
  const char const *fsblacklist[] =
    {"sysfs", "proc", "tmpfs", "devtmpfs", "devpts",
     "securityfs", "pstore", "cgroup2", "fuse.portal"};
  const int nblack = sizeof(fsblacklist)/sizeof(fsblacklist[0]);
  char namebuf[PATH_MAX];
  char devname[NAME_MAX];
  struct mntent *ent;
  char *dpath;
  int q = 0;
   
  /* List all the disks involved by all listed filesystems */
  while( (ent = getmntent(pf)) )
    {
      int p, i;
      char c;
      char name[NAME_MAX+1], *pname, *syspath;
      /* Don't waste time for exotic or pseudo filesystems */
      /* which are present in /proc/mounts */
      for(i=0; i<nblack && strcmp(fsblacklist[i], ent->mnt_type); i++) /*nop*/;
      if(i!=nblack) continue;
      strLcpy(namebuf, ent->mnt_fsname, sizeof(namebuf));
      strLcpy(devname, basename(namebuf), sizeof(devname));
      if(!strcmp(devname, blkname)) q = 1;
      /* Don't list filesystems mounted under /media */
      if(!strncmp("/media/", ent->mnt_dir, 7)) continue; 
      /*
        printf("lstab: listing disks for %s.\n", devname);
        fflush(stdout);
      */
      dpath = devpath(devname, namebuf);
      lookup_disk(dpath, add_to_list);
    }
  endmntent(pf);
  return q;
  /* The return code only tells if the filesystem is already mounted */ 
}
