<commit_before>/*
 *  einit-mount.c
 *  eINIT
 *
 *  Created by <NAME> on 07/06/2006.
 *  Renamed from common-mount.c on 11/10/2006.
 *  Copyright 2006 <NAME>. All rights reserved.
 *
 */

/*
Copyright (c) 2006, <NAME>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
	  this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
	  this list of conditions and the following disclaimer in the documentation
	  and/or other materials provided with the distribution.
    * Neither the name of the project nor the names of its contributors may be
	  used to endorse or promote products derived from this software without
	  specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#define _MODULE
#include <einit/common-mount.h>

#include <stdio.h>
#include <einit/module.h>
#include <einit/config.h>
#include <einit/utility.h>
#include <einit/bitch.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pthread.h>
#include <einit/dexec.h>
#include <einit/pexec.h>
#include <sys/mount.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#ifdef LINUX
#include <linux/fs.h>

#ifndef MNT_DETACH
/* this somehow doesn't always get defined... *shrugs* */
#define MNT_DETACH   0x00000002
#endif

#endif

#ifdef POSIXREGEX
#include <regex.h>
#endif

#define EXPECTED_EIV 1

#if EXPECTED_EIV != EINIT_VERSION
#warning "This module was developed for a different version of eINIT, you might experience problems"
#endif

/* module definitions */
char *provides[] = {"mount", NULL};
const struct smodule self = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_LOADER,
	.options	= 0,
	.name		= "Filesystem-Mounter",
	.rid		= "einit-mount",
	.provides	= provides,
	.requires	= NULL,
	.notwith	= NULL
};

char *provides_mountlocal[] = {"mount/local", NULL};
char *requires_mountlocal[] = {"/", "mount/system", "mount/critical", NULL};
struct smodule sm_mountlocal = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (local)",
	.rid		= "einit-mount-local",
	.provides	= provides_mountlocal,
	.requires	= requires_mountlocal,
	.notwith	= NULL
};

char *provides_mountremote[] = {"mount/remote", NULL};
char *requires_mountremote[] = {"/", "mount/system", "network", "portmap", NULL};
struct smodule sm_mountremote = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (remote)",
	.rid		= "einit-mount-remote",
	.provides	= provides_mountremote,
	.requires	= requires_mountremote,
	.notwith	= NULL
};

char *provides_system[] = {"mount/system", NULL};
char *requires_system[] = {"/", NULL};
struct smodule sm_system = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (system)",
	.rid		= "einit-mount-system",
	.provides	= provides_system,
	.requires	= requires_system,
	.notwith	= NULL
};

char *provides_critical[] = {"mount/critical", NULL};
char *requires_critical[] = {"/", "mount/system", NULL};
struct smodule sm_critical = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (critical)",
	.rid		= "einit-mount-critical",
	.provides	= provides_critical,
	.requires	= requires_critical,
	.notwith	= NULL
};

char *provides_root[] = {"/", NULL};
struct smodule sm_root = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (/)",
	.rid		= "einit-mount-root",
	.provides	= provides_root,
	.requires	= NULL,
	.notwith	= NULL
};

/* variable definitions */
pthread_mutex_t blockdevices_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtab_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t fstab_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t fs_mutex = PTHREAD_MUTEX_INITIALIZER;
char *fslist_hr[] = {
 "unknown",
 "ext2",
 "ext3",
 "reiserfs",
 "reiser4",
 "jfs",
 "xfs",
 "ufs"
};
char *defaultblockdevicesource[] = {"dev", NULL};
char *defaultfstabsource[] = {"configuration", NULL};
char *defaultmtabsource[] = {"legacy", NULL};
char *defaultfilesystems[] = {"linux", NULL};
char *fsck_command = NULL;

struct mount_control_block mcb = {
	 .blockdevices		= NULL,
	 .fstab			= NULL,
	 .mtab			= NULL,
	 .filesystems		= NULL,
	 .add_block_device	= add_block_device,
	 .add_fstab_entry	= add_fstab_entry,
	 .add_mtab_entry	= add_mtab_entry,
	 .add_filesystem	= add_filesystem,
	 .update_options	= EVENT_UPDATE_METADATA + EVENT_UPDATE_BLOCK_DEVICES + EVENT_UPDATE_FSTAB + EVENT_UPDATE_MTAB,
	 .critical		= NULL
};

/* function declarations */
int scanmodules (struct lmodule *);
int configure (struct lmodule *);
int cleanup (struct lmodule *);
int enable (enum mounttask, struct einit_event *);
int disable (enum mounttask, struct einit_event *);
int mountwrapper (char *, struct einit_event *, uint32_t);

/* function definitions */
int examine_configuration (struct lmodule *irr) {
 int pr = 0;
 char **tmpset, *tmpstring;

 if (!(tmpstring = cfg_getstring("mount-fstab-source", NULL))) {
  fputs (" * configuration variable \"mount-fstab-source\" not found.\n", stderr);
  pr++;
 } else {
  tmpset = str2set(':', tmpstring);

  if (inset ((void **)tmpset, (void *)"label", SET_TYPE_STRING)) {
   if (!(mcb.update_options & EVENT_UPDATE_METADATA)) {
    fputs (" * fstab-source \"label\" to be used, but optional update-step \"metadata\" not enabled.\n", stderr);
    pr++;
   }
   if (!(mcb.update_options & EVENT_UPDATE_BLOCK_DEVICES)) {
    fputs (" * fstab-source \"label\" to be used, but optional update-step \"block-devices\" not enabled.\n", stderr);
    pr++;
   }
  }

  if (!inset ((void **)tmpset, (void *)"configuration", SET_TYPE_STRING)) {
   fputs (" * fstab-source \"configuration\" disabled! In 99.999% of all cases, you don't want to do that!\n", stderr);
   pr++;
  }

  if (inset ((void **)tmpset, (void *)"legacy", SET_TYPE_STRING)) {
   fputs (" * fstab-source \"legacy\" enabled; you shouldn't rely on that.\n", stderr);
   pr++;
  }

  free (tmpset);
 }

 if (mcb.update_options & EVENT_UPDATE_METADATA) {
  if (!(mcb.update_options & EVENT_UPDATE_BLOCK_DEVICES)) {
   fputs (" * update-step \"metadata\" cannot be performed without update-step \"block-devices\".\n", stderr);
   pr++;
  }
 } else {
  fputs (" * update-step \"metadata\" disabled; not a problem per-se, but this will prevent your filesystems from being automatically fsck()'d.\n", stderr);
 }

 if (!mcb.fstab) {
  fputs (" * your fstab is empty.\n", stderr);
  pr++;
 } else {
  struct uhash *thash;
  if (!(thash = hashfind (mcb.fstab, "/"))) {
   fputs (" * your fstab does not contain an entry for \"/\".\n", stderr);
   pr++;
  } else if (!(((struct fstab_entry *)(thash->value))->device)) {
   fputs (" * you have apparently forgotten to specify a device for your root-filesystem.\n", stderr);
   pr++;
  } else if (!strcmp ("/dev/ROOT", (((struct fstab_entry *)(thash->value))->device))) {
   fputs (" * you didn't edit your rc.xml to specify your root-filesystem.\n", stderr);
   pr++;
  }
 }

 return pr;
}


int configure (struct lmodule *this) {
 struct cfgnode *node = NULL;

/* pexec configuration */<commit_msg>better problem-scans<commit_after>/*
 *  einit-mount.c
 *  eINIT
 *
 *  Created by <NAME> on 07/06/2006.
 *  Renamed from common-mount.c on 11/10/2006.
 *  Copyright 2006 <NAME>. All rights reserved.
 *
 */

/*
Copyright (c) 2006, <NAME>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice,
	  this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice,
	  this list of conditions and the following disclaimer in the documentation
	  and/or other materials provided with the distribution.
    * Neither the name of the project nor the names of its contributors may be
	  used to endorse or promote products derived from this software without
	  specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#define _MODULE
#include <einit/common-mount.h>

#include <stdio.h>
#include <einit/module.h>
#include <einit/config.h>
#include <einit/utility.h>
#include <einit/bitch.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <pthread.h>
#include <einit/dexec.h>
#include <einit/pexec.h>
#include <sys/mount.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#ifdef LINUX
#include <linux/fs.h>

#ifndef MNT_DETACH
/* this somehow doesn't always get defined... *shrugs* */
#define MNT_DETACH   0x00000002
#endif

#endif

#ifdef POSIXREGEX
#include <regex.h>
#endif

#define EXPECTED_EIV 1

#if EXPECTED_EIV != EINIT_VERSION
#warning "This module was developed for a different version of eINIT, you might experience problems"
#endif

/* module definitions */
char *provides[] = {"mount", NULL};
const struct smodule self = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_LOADER,
	.options	= 0,
	.name		= "Filesystem-Mounter",
	.rid		= "einit-mount",
	.provides	= provides,
	.requires	= NULL,
	.notwith	= NULL
};

char *provides_mountlocal[] = {"mount/local", NULL};
char *requires_mountlocal[] = {"/", "mount/system", "mount/critical", NULL};
struct smodule sm_mountlocal = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (local)",
	.rid		= "einit-mount-local",
	.provides	= provides_mountlocal,
	.requires	= requires_mountlocal,
	.notwith	= NULL
};

char *provides_mountremote[] = {"mount/remote", NULL};
char *requires_mountremote[] = {"/", "mount/system", "network", "portmap", NULL};
struct smodule sm_mountremote = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (remote)",
	.rid		= "einit-mount-remote",
	.provides	= provides_mountremote,
	.requires	= requires_mountremote,
	.notwith	= NULL
};

char *provides_system[] = {"mount/system", NULL};
char *requires_system[] = {"/", NULL};
struct smodule sm_system = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (system)",
	.rid		= "einit-mount-system",
	.provides	= provides_system,
	.requires	= requires_system,
	.notwith	= NULL
};

char *provides_critical[] = {"mount/critical", NULL};
char *requires_critical[] = {"/", "mount/system", NULL};
struct smodule sm_critical = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (critical)",
	.rid		= "einit-mount-critical",
	.provides	= provides_critical,
	.requires	= requires_critical,
	.notwith	= NULL
};

char *provides_root[] = {"/", NULL};
struct smodule sm_root = {
	.eiversion	= EINIT_VERSION,
	.version	= 1,
	.mode		= EINIT_MOD_EXEC,
	.options	= 0,
	.name		= "mount (/)",
	.rid		= "einit-mount-root",
	.provides	= provides_root,
	.requires	= NULL,
	.notwith	= NULL
};

/* variable definitions */
pthread_mutex_t blockdevices_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mtab_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t fstab_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t fs_mutex = PTHREAD_MUTEX_INITIALIZER;
char *fslist_hr[] = {
 "unknown",
 "ext2",
 "ext3",
 "reiserfs",
 "reiser4",
 "jfs",
 "xfs",
 "ufs"
};
char *defaultblockdevicesource[] = {"dev", NULL};
char *defaultfstabsource[] = {"configuration", NULL};
char *defaultmtabsource[] = {"legacy", NULL};
char *defaultfilesystems[] = {"linux", NULL};
char *fsck_command = NULL;

struct mount_control_block mcb = {
	 .blockdevices		= NULL,
	 .fstab			= NULL,
	 .mtab			= NULL,
	 .filesystems		= NULL,
	 .add_block_device	= add_block_device,
	 .add_fstab_entry	= add_fstab_entry,
	 .add_mtab_entry	= add_mtab_entry,
	 .add_filesystem	= add_filesystem,
	 .update_options	= EVENT_UPDATE_METADATA + EVENT_UPDATE_BLOCK_DEVICES + EVENT_UPDATE_FSTAB + EVENT_UPDATE_MTAB,
	 .critical		= NULL
};

/* function declarations */
int scanmodules (struct lmodule *);
int configure (struct lmodule *);
int cleanup (struct lmodule *);
int enable (enum mounttask, struct einit_event *);
int disable (enum mounttask, struct einit_event *);
int mountwrapper (char *, struct einit_event *, uint32_t);

/* function definitions */

/* error checking... */
int examine_configuration (struct lmodule *irr) {
 int pr = 0;
 char **tmpset, *tmpstring;

 if (!(tmpstring = cfg_getstring("mount-fstab-source", NULL))) {
  fputs (" * configuration variable \"mount-fstab-source\" not found.\n", stderr);
  pr++;
 } else {
  tmpset = str2set(':', tmpstring);

  if (inset ((void **)tmpset, (void *)"label", SET_TYPE_STRING)) {
   if (!(mcb.update_options & EVENT_UPDATE_METADATA)) {
    fputs (" * fstab-source \"label\" to be used, but optional update-step \"metadata\" not enabled.\n", stderr);
    pr++;
   }
   if (!(mcb.update_options & EVENT_UPDATE_BLOCK_DEVICES)) {
    fputs (" * fstab-source \"label\" to be used, but optional update-step \"block-devices\" not enabled.\n", stderr);
    pr++;
   }
  }

  if (!inset ((void **)tmpset, (void *)"configuration", SET_TYPE_STRING)) {
   fputs (" * fstab-source \"configuration\" disabled! In 99.999% of all cases, you don't want to do that!\n", stderr);
   pr++;
  }

  if (inset ((void **)tmpset, (void *)"legacy", SET_TYPE_STRING)) {
   fputs (" * fstab-source \"legacy\" enabled; you shouldn't rely on that.\n", stderr);
   pr++;
  }

  free (tmpset);
 }

 if (mcb.update_options & EVENT_UPDATE_METADATA) {
  if (!(mcb.update_options & EVENT_UPDATE_BLOCK_DEVICES)) {
   fputs (" * update-step \"metadata\" cannot be performed without update-step \"block-devices\".\n", stderr);
   pr++;
  }
 } else {
  fputs (" * update-step \"metadata\" disabled; not a problem per-se, but this will prevent your filesystems from being automatically fsck()'d.\n", stderr);
 }

 if (!mcb.fstab) {
  fputs (" * your fstab is empty.\n", stderr);
  pr++;
 } else {
  struct uhash *thash, *fhash;
  if (!(thash = hashfind (mcb.fstab, "/"))) {
   fputs (" * your fstab does not contain an entry for \"/\".\n", stderr);
   pr++;
  } else if (!(((struct fstab_entry *)(thash->value))->device)) {
   fputs (" * you have apparently forgotten to specify a device for your root-filesystem.\n", stderr);
   pr++;
  } else if (!strcmp ("/dev/ROOT", (((struct fstab_entry *)(thash->value))->device))) {
   fputs (" * you didn't edit your rc.xml to specify your root-filesystem.\n", stderr);
   pr++;
  }

  thash = mcb.fstab;
  while (thash) {
   struct stat stbuf;

   if (!(((struct fstab_entry *)(thash->value))->fs) || !strcmp ("auto", (((struct fstab_entry *)(thash->value))->fs))) {
    fprintf (stderr, " * no filesystem type specified for fstab-node \"%s\", or type set to auto -- eINIT cannot do that, yet, please specify the filesystem type.\n", thash->key);
    pr++;
   }

   if (!(((struct fstab_entry *)(thash->value))->device)) { 
    if ((((struct fstab_entry *)(thash->value))->fs) && (fhash = hashfind (mcb.filesystems, (((struct fstab_entry *)(thash->value))->fs))) && !((uintptr_t)fhash->value & FS_CAPA_VOLATILE)) {
     fprintf (stderr, " * no device specified for fstab-node \"%s\", and filesystem does not have the volatile-attribute.\n", thash->key);
     pr++;
    }
   } else if (stat ((((struct fstab_entry *)(thash->value))->device), &stbuf) == -1) {
    fprintf (stderr, " * cannot stat device \"%s\" from node \"%s\", the error was \"%s\".\n", (((struct fstab_entry *)(thash->value))->device), thash->key, strerror (errno));
    pr++;
   }
   thash = hashnext (thash);
  }
 }

 return pr;
}

/* the actual module */

int configure (struct lmodule *this) {
 struct cfgnode *node = NULL;

/* pexec configuration */
{'fraction_non_alphanumeric': 0.14369585043319655, 'fraction_numerical': 0.0066689466484268125, 'mean_word_length': 4.134621012584138, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 77, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '497737', 'n_tokens_mistral': 6380, 'n_tokens_neox': 6018, 'n_words': 1775}