*/
+#define _GNU_SOURCE 1 /* for memrchr() */
+
#include "config.h"
#undef FALSE
#include <errno.h>
#include <unistd.h>
#include "../libcaptive-install/proc_partitions.h"
+#include <ctype.h>
#include <captive/macros.h>
+#include <captive/client.h>
#include <ntfs/volume.h>
{
struct mntent mntent_local;
gint dir_count;
+gchar *s;
g_return_if_fail(device!=NULL);
g_return_if_fail(vol_name!=NULL);
g_return_if_fail(mntentfilew!=NULL);
+ vol_name=captive_strdup_alloca(vol_name);
+ for (s=(/* de-const */ gchar *)vol_name;*s;s++) {
+ if (!isalnum(*s))
+ *s='_';
+ else
+ *s=tolower(*s);
+ }
+ if (!*vol_name)
+ vol_name="noname";
+
CAPTIVE_MEMZERO(&mntent_local);
mntent_local.mnt_fsname=(/* de-const */ gchar *)device;
mntent_local.mnt_dir=(/* de-const */ gchar *)captive_printf_alloca("/mnt/captive-%s",vol_name);
g_warning(_("Error creating mount directory \"%s\" for device \"%s\": %m"),
mntent_local.mnt_dir,mntent_local.mnt_fsname);
mntent_local.mnt_type="captive-ntfs";
- mntent_local.mnt_opts="defaults"; /* 'mntent_local.mnt_opts' must be != NULL ! */
+ mntent_local.mnt_opts="defaults,noauto"; /* 'mntent_local.mnt_opts' must be != NULL ! */
if (optarg_verbose)
g_message(_("Creating captive-ntfs mntent: %s -> %s"),mntent_local.mnt_fsname,mntent_local.mnt_dir);
if (addmntent(mntentfilew,&mntent_local))
int errint;
FILE *mntentfiler,*mntentfilew;
gboolean modified=FALSE;
+GHashTable *proc_partitions_ntfs_hash;
+struct mntent *mntent;
+gchar *mntent_mem=NULL;
+size_t mntent_mem_alloc=0;
- /* Initialize the i18n stuff */
- setlocale(LC_ALL,"");
- bindtextdomain(PACKAGE,LOCALEDIR);
- textdomain(PACKAGE);
+ captive_standalone_init();
context=poptGetContext(
PACKAGE, /* name */
if (!(mntentfilew=setmntent((optarg_dry ? "/dev/null" : FILENAME_ETC_FSTAB_TMP),"w")))
g_error(_("Cannot open \"%s\" for writing: %m"),FILENAME_ETC_FSTAB_TMP);
- switch (optarg_mode) {
-
- case OPTARG_MODE_ADD: {
-GHashTable *proc_partitions_ntfs_hash;
-struct mntent *mntent;
-
- proc_partitions_ntfs_hash=proc_partitions_ntfs_hash_get(optarg_verbose);
- while ((mntent=getmntent(mntentfiler))) {
- if (!g_hash_table_lookup(proc_partitions_ntfs_hash,mntent->mnt_fsname)) {
- if (!strcmp(mntent->mnt_type,"captive-ntfs")
- && !strncmp(mntent->mnt_fsname,"/dev/",strlen("/dev/"))) {
- g_warning(_("Dropping no-longer valid captive filesystem mntent from \"%s\" of device: %s"),
- FILENAME_ETC_FSTAB,mntent->mnt_fsname);
- modified=TRUE;
- continue;
- }
- if (addmntent(mntentfilew,mntent))
- g_error(_("Error copying mntent for device \"%s\": %m"),mntent->mnt_fsname);
- g_hash_table_insert(dirs_used_hash,g_strdup(mntent->mnt_dir),dirs_used_hash);
- }
- else {
- /* Original mntent is dropped to be replaced by new one. */
- if (optarg_verbose)
- g_message(_("Dropping captive mntent to be replaced by new one: %s"),mntent->mnt_fsname);
- modified=TRUE;
- }
+ proc_partitions_ntfs_hash=proc_partitions_ntfs_hash_get(optarg_verbose);
+ do {
+long mntent_offset_start,mntent_offset_end;
+gchar *mntent_mem_last_line;
+size_t mntent_mem_len, mntent_mem_last_line_len;
+
+ mntent_offset_start=ftell(mntentfiler);
+ mntent=getmntent(mntentfiler);
+ mntent_offset_end=ftell(mntentfiler);
+ g_assert(mntent_offset_end>=mntent_offset_start);
+ mntent_mem_len=mntent_offset_end-mntent_offset_start;
+ if (mntent_mem_len>mntent_mem_alloc) {
+ g_free(mntent_mem);
+ mntent_mem_alloc=2*mntent_mem_len;
+ mntent_mem=g_malloc(mntent_mem_alloc);
+ }
+ if (fseek(mntentfiler,mntent_offset_start,SEEK_SET))
+ g_warning(_("Error seeking in \"%s\": %m"),FILENAME_ETC_FSTAB);
+ if (mntent_mem_len!=fread(mntent_mem,1,mntent_mem_len,mntentfiler))
+ g_warning(_("Error reading \"%s\": %m"),FILENAME_ETC_FSTAB);
+ mntent_mem_last_line=NULL;
+ if (mntent_offset_end!=ftell(mntentfiler))
+ g_warning(_("Invalid position in \"%s\" after fread(3): %m"),FILENAME_ETC_FSTAB);
+ if (mntent_mem_len) {
+size_t comments_len;
+
+ if (mntent_mem[mntent_mem_len-1]!='\n')
+ g_warning(_("mntent memory block not newline-terminated from \"%s\""),FILENAME_ETC_FSTAB);
+ if ((mntent_mem_last_line=memrchr(mntent_mem,'\n',mntent_mem_len-1))) {
+ mntent_mem_last_line++;
+ comments_len=mntent_mem_last_line-mntent_mem;
+ mntent_mem_last_line_len=mntent_mem_len-comments_len;
+ if (comments_len!=fwrite(mntent_mem,1,comments_len,mntentfilew))
+ g_error(_("Error copying comments before device \"%s\" to \"%s\": %m"),
+ (!mntent ? "<none>" : mntent->mnt_fsname),FILENAME_ETC_FSTAB_TMP);
}
- if (g_hash_table_size(proc_partitions_ntfs_hash))
- modified=TRUE;
- g_hash_table_foreach(proc_partitions_ntfs_hash,
- (GHFunc)mntent_add_proc_partitions_ntfs_hash_entry, /* func */
- mntentfilew); /* user_data */
- g_hash_table_destroy(proc_partitions_ntfs_hash);
- } break;
-
- case OPTARG_MODE_REMOVE: {
-struct mntent *mntent;
+ }
+ if (!mntent_mem_last_line) {
+ mntent_mem_last_line=mntent_mem;
+ mntent_mem_last_line_len=mntent_mem_len;
+ }
+ if (mntent
+ && !strcmp(mntent->mnt_type,"captive-ntfs")
+ && !strncmp(mntent->mnt_fsname,"/dev/",strlen("/dev/"))) {
+ switch (optarg_mode) {
- while ((mntent=getmntent(mntentfiler))) {
- if (!strcmp(mntent->mnt_type,"captive-ntfs")
- && !strncmp(mntent->mnt_fsname,"/dev/",strlen("/dev/"))) {
+ case OPTARG_MODE_REMOVE:
if (optarg_verbose)
g_message(_("Dropping captive mntent: %s"),mntent->mnt_fsname);
if (optarg_dry || !rmdir(mntent->mnt_dir)) {
mntent->mnt_dir,mntent->mnt_fsname);
modified=TRUE;
continue;
- }
- if (addmntent(mntentfilew,mntent))
- g_error(_("Error copying mntent for device \"%s\": %m"),mntent->mnt_fsname);
+ /* NOTREACHED */
+
+ case OPTARG_MODE_ADD:
+ if (!g_hash_table_lookup(proc_partitions_ntfs_hash,mntent->mnt_fsname))
+ g_warning(_("Dropping no-longer valid captive filesystem mntent from \"%s\" of device: %s"),
+ FILENAME_ETC_FSTAB,mntent->mnt_fsname);
+ else {
+ /* Original mntent is dropped to be replaced by new one. */
+ if (optarg_verbose)
+ g_message(_("Dropping captive mntent to be replaced by new one: %s"),mntent->mnt_fsname);
+ }
+ modified=TRUE;
+ continue;
+ /* NOTREACHED */
+
+ default: g_assert_not_reached();
}
- } break;
+ }
+ if (mntent_mem_last_line_len!=fwrite(mntent_mem_last_line,1,mntent_mem_last_line_len,mntentfilew))
+ g_error(_("Error copying mntent for device \"%s\" to \"%s\": %m"),mntent->mnt_fsname,FILENAME_ETC_FSTAB_TMP);
+ if (mntent)
+ g_hash_table_insert(dirs_used_hash,g_strdup(mntent->mnt_dir),dirs_used_hash);
+ } while (mntent);
+ g_free(mntent_mem);
+ if (optarg_mode==OPTARG_MODE_ADD) {
+ if (g_hash_table_size(proc_partitions_ntfs_hash))
+ modified=TRUE;
+ g_hash_table_foreach(proc_partitions_ntfs_hash,
+ (GHFunc)mntent_add_proc_partitions_ntfs_hash_entry, /* func */
+ mntentfilew); /* user_data */
}
+ g_hash_table_destroy(proc_partitions_ntfs_hash);
if (optarg_verbose)
g_message(_("Modified status: %s"),(modified ? _("YES") : _("NO")));