/*
 * SPDX-FileCopyrightText: 2026 Didier Kryn <kryn@in2p3.fr>
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
#include <sys/mount.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <fcntl.h>  // O_DIRECTORY
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
/*------------- Internationalization -------------*/
#include <libintl.h>
#define _(StRiNg) gettext(StRiNg)
#define gettext_noop(String) String
#define N_(String) gettext_noop(String)
/*------------------------------------------------*/

/*========= Unmount the filesystem and remove the mount point ==========*/
int dmount(const char *username, const char *targetname)
{
  int q, dirfd;
  char pathname[PATH_MAX];
  char buf[PATH_MAX + 16]; // 16 bytes extra for "umount ", "rmdir " and '\0'
  struct stat sb1, sb2;
  if(strlen(username)+strlen(targetname) > 248) goto path_error;
  snprintf(pathname, sizeof(pathname), "/media/%s/%s", username, targetname);

  /*------- Check if the target is a mountpoint. If yes, unmount it ------*/
  dirfd = open(pathname, O_DIRECTORY);
  if(dirfd<0) goto target_error;
  if( fstat(dirfd, &sb1) ) goto target_error;
  if( fstatat(dirfd, "..", &sb2, 0) ) goto target_error;
  close(dirfd); /* Must close it *before* umount */

  /* MNT_DETACH allows a "lazy unmount" if the if the resource is busy;
   * otherwise, 0 or UMOUNT_NOFOLLOW is enough */
  if( sb1.st_dev != sb2.st_dev && umount2(pathname, MNT_DETACH) )
    goto umount_error;

  /*----------------------- remove the directory --------------------------*/
  if( rmdir(pathname) == -1 && errno != ENOENT )  goto rmdir_error;
  return 0;

 path_error:
  fputs(_("Name of mountpoint is too long.\n"), stderr);
  return 1;
 target_error:
  perror(pathname);
  return 1;
 umount_error:
  snprintf(buf, sizeof(buf), "umount %s", pathname);
  perror(buf);
  return 1;
 rmdir_error:
  snprintf(buf, sizeof(buf), "rmdir %s", pathname);
  perror(buf);
  return 1;
}



