/*********************************************************************
 *
 *            EZFM---EZWGL based file manager for X11
 *
 *             Copyright (C) 1998  Maorong Zou
 *
 *
 *  This file is part of EZFM.
 *
 *  EZFM is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * EZFM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EZFM; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 *************************************************************************/


#define _MNT1_C_
#include "ezfm.h"

/*************************************************************************/

#ifdef REMOVABLE_DRIVES

#include <mntent.h>

void ezfmMount  MY_ANSIARGS((char *mpt, int idx, int msgId));
void ezfmuMount MY_ANSIARGS((char *mpt, int idx, int msgId));

int  ezfmIsMounted MY_ANSIARGS((char *mpt, int conly));
int  ezfmIsInFstab MY_ANSIARGS((char *mpt, int conly));

void  ezfmUpdateMountTable   MY_ANSIARGS ((void));
void  ezfmUpdateMountTable1  MY_ANSIARGS ((char *mpt));

void openDrive  MY_ANSIARGS((void *widget, void *data));
void mountDrive  MY_ANSIARGS((char *mountPt, int idx, Folder *folder));
void umountDrive  MY_ANSIARGS((char *mountPt, int idx));

/*************************************************************************/
static void announceMountChange MY_ANSIARGS((int nargs, void **args));
static void mountWork MY_ANSIARGS((char *mpt, int which, int idx, int mId));
/*************************************************************************/
#define  _UMOUNT_         0
#define  _MOUNT_          1
/*************************************************************************/
void ezfmMount(mpt, idx, mid) char *mpt; int mid; int idx;
{
  mountWork(mpt, _MOUNT_, idx,  mid);
}
void ezfmUMount(mpt, idx, mid) char *mpt; int mid; int idx;
{
  mountWork(mpt, _UMOUNT_, idx, mid);
}
/*************************************************************************/
static void announceMountChange(nargs, args)
     int nargs; void **args;
{
  char *mpoint = (char *)args[0];
  char *cmd = (char *)args[1];
  int  mid = (int)args[2];
  int  idx = (int)args[3];
  char message[256];

  if(cmd != NULL) /* command was mount */
    {
      if(ezfmIsMounted(mpoint, 1)) /* mpoint has been mount succesfully */
	{
	  sprintf(message, "M%s", mpoint);
	  strcpy(message+128, ezfmHostname);
	  EZ_BroadcastMessage(ezfmMsgMountTbChangeAtom, message, 256, mid, 0); 
	  /*printf("Message [%s] [%s] sent \n", message, message+128);*/
	}
    }
  else           /* command was umount */
    {
      if(!ezfmIsMounted(mpoint, 1)) /* umount was succeful */
	{
	  sprintf(message, "U%s", mpoint);
	  strcpy(message+128, ezfmHostname);
	  EZ_BroadcastMessage(ezfmMsgMountTbChangeAtom, message, 256, mid, 0);      
	  /* printf("Message [%s] [%s] sent \n", message, message+128);*/
	}
    }
  ezfmDrives[idx].blocked  -= 1;
  /*printf("Remove lock on [%d] = %d\n", idx, ezfmDrives[idx].blocked);*/
  if(mpoint) EZ_Free(mpoint);
}

static void mountWork(mpoint, which, idx, msgId) 
     char *mpoint;  /* the mounting point */
     int  which;    /* MOUNT or UMOUNT    */
     int  idx;
     int  msgId;
{
  char   command[1024];
  void   *args[4];
  char   *mptSave;

  if(mpoint == NULL || mpoint[0] != '/')
    {
      sprintf(command, "Mounting point '%s' is not an absolute pathname", mpoint);
      ezfmExecutionError("mount/umount", command);
      return;
    }
  if(which == _MOUNT_) 
    {
      if(ezfmIsMounted(mpoint, 1)) return;        /* already mounted */
      sprintf(command, "%s %s", BIN_MOUNT, mpoint);
    }
  else 
    {
      if(!ezfmIsMounted(mpoint, 1)) return;      /* not currently mounted */
      sprintf(command, "%s %s", BIN_UMOUNT, mpoint);
    }
  mptSave = (char *)EZ_Malloc( (strlen(mpoint) + 1) * sizeof(char));
  strcpy(mptSave, mpoint);
  args[0] = mptSave;
  args[1] = (which == _MOUNT_? mptSave : NULL); /* flag mount/umount */
  args[2] = (void *)msgId;
  args[3] = (void *)idx;

  ezfmDrives[idx].blocked += 1;  
  /* printf("Set lock on [%d] = %d\n", idx, ezfmDrives[idx].blocked);*/

  executeShCmd(command, announceMountChange, 4, args);
}
/*************************************************************************/
static int mntentIsIn(mpt, file, conly) char *mpt; char *file; int conly;
{
  FILE *fp = setmntent(file, "r");
  struct mntent  *ent;
  int isIn = 0;
  if(fp == NULL) 
    {
      if(!conly) ezfmWarning("Cannot open", file);
    }
  else
    {
      while( (ent = getmntent(fp)) != NULL)
	{
	  if(!strcmp(ent->mnt_dir, mpt))
	    {
	      isIn = 1;
	      break;
	    }
	}
    }
  endmntent(fp);
  return(isIn);
}
/*************************************************************************/
int  ezfmIsMounted(mpt, flag) char *mpt; int flag;
{ return(mntentIsIn(mpt, MOUNTED,flag)); }

int  ezfmIsInFstab(mpt,flag) char *mpt; int flag;
{ return(mntentIsIn(mpt, MNTTAB, flag)); }

/*************************************************************************
 * Updae mount table
 */
void ezfmUpdateMountTable()
{
  int i, cnt, old[8];
  FILE *fp = setmntent(MOUNTED, "r");
  if(fp != NULL) 
    {
      struct mntent  *ent;
      for(cnt = 0; cnt < 8 && ezfmDrives[cnt].status >= 0; cnt++) 
	{old[cnt] = ezfmDrives[cnt].status; ezfmDrives[cnt].status = 0;}
      
      while( (ent = getmntent(fp)) != NULL)
	{
	  for(i = 0; i < cnt; i++)
	    {
	      if(!strcmp(ent->mnt_dir, ezfmDrives[i].mntPt))
		ezfmDrives[i].status = 1;
	    }
	}
      endmntent(fp);
      for(i = 0; i < cnt; i++) 
	{
	  if(old[i] != ezfmDrives[i].status)
	    {
	      updateDriveMenusAndButtons();
	      break;
	    }
	}
    }
}

void ezfmUpdateMountTable1(mpoint) char *mpoint;
{
  int i;
  for(i = 0; i < 8 && ezfmDrives[i].status >= 0; i++)
    {
      if(!strcmp(mpoint, ezfmDrives[i].mntPt))
	{
	  int oldstatus = ezfmDrives[i].status;
	  int newstatus = ezfmIsMounted(ezfmDrives[i].mntPt, 1);
	  ezfmDrives[i].status = newstatus;
	  if(oldstatus != newstatus)
	    updateDriveMenusAndButtons();
	  break;
	}
    }
}
/***************************************************************************/
void openDrive(widget, data)
     EZ_Widget *widget; void *data;
{
  int                idx;
  idx = EZ_GetWidgetIntData(widget);
  if(idx < 8 && idx >= 0)
    {
      char *name = ezfmDrives[idx].mntPt;
      Toplevel  *tp = (Toplevel *)data;
      Folder    *folder = NULL;
      if(tp)
	{
	  folder = tp->activeFolder;
	  if(folder == NULL) folder = tp->folder[0];
	}
      if(ezfmIsMounted(name, 1))
	{
	  ezfmDrives[idx].status = 1;
	  OpenFolder(name,folder, 1, 0);
	}
      else 
	{
	  mountDrive(name, idx, folder);
	}
    }
}
/*************************************************************************/
void msgOpenMountedFolder(msg, data)
     EZ_Message *msg; void *data;
{
  /* message: the first 128 bytes:   [MU]mountPoint    
   *          the second 128 bytes:  hostname;
   */
  if(msg->messageLength > 0)
    {
      char *message = msg->message;
      char *hostname = message+128;
      /* printf("Message Received: [%s] [%s]\n", message, hostname);*/
      if(!strcmp(hostname, ezfmHostname))
	{
	  char isMounted = (message[0] == 'M');
	  char *mpoint = message+1;
	  ezfmUpdateMountTable1(mpoint);
	  if(isMounted) OpenFolder(mpoint, data, 1, 0);
	}
      EZ_DeleteMessageHandler(ezfmMsgMountTbChangeAtom, msg->messageId, data, msgOpenMountedFolder);
    }
}

/************************************************************************************/
void mountDrive(mpt, idx, folder)
     char *mpt; int idx; Folder *folder;
{
  if(mpt)
    {
      char      pathname[256];
      strcpy(pathname, mpt);
      if(!ezfmIsMounted(pathname, 1))
	{
	  if(ezfmIsInFstab(pathname,1))
	    {
	      int mid = (rand()>>5);
	      EZ_RegisterMessageHandler(ezfmMsgMountTbChangeAtom, mid, folder, msgOpenMountedFolder, 30, NULL, NULL);
	      ezfmMount(pathname, idx, mid);
	    }
	  else ezfmWarning(pathname, "is not in /etc/fstab");
	}
      else  ezfmWarning(pathname, "is already mounted");
    }
}
/************************************************************************************/
void umountDrive(mpt,idx)
     char *mpt; int idx;
{
  if(mpt)
    {
      char      pathname[256];
      strcpy(pathname, mpt);
      if(ezfmIsMounted(pathname, 1))
	ezfmUMount(pathname, idx, 0);
      else  ezfmWarning(pathname, "is not mounted");
    }
}
/*************************************************************************/
#endif

#undef _MNT1_C_




