예제 #1
0
static int
mount_cdfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
  cdfs_args_t cdfs_args;
  mntent_t mnt;
  int genflags, cdfs_flags, retval;

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_CDFS;

  memset((voidp) &cdfs_args, 0, sizeof(cdfs_args)); /* Paranoid */
  cdfs_flags = 0;

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = fs_name;
  mnt.mnt_type = MNTTAB_TYPE_CDFS;
  mnt.mnt_opts = opts;

#if defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_DEFPERM))
# ifdef MNT2_CDFS_OPT_DEFPERM
    cdfs_flags |= MNT2_CDFS_OPT_DEFPERM;
# else /* not MNT2_CDFS_OPT_DEFPERM */
    cdfs_flags &= ~MNT2_CDFS_OPT_NODEFPERM;
# endif /* not MNT2_CDFS_OPT_DEFPERM */
#endif /* defined(MNT2_CDFS_OPT_DEFPERM) && defined(MNTTAB_OPT_DEFPERM) */

#if defined(MNT2_CDFS_OPT_NODEFPERM) && defined(MNTTAB_OPT_NODEFPERM)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NODEFPERM))
    cdfs_flags |= MNT2_CDFS_OPT_NODEFPERM;
#endif /* MNTTAB_OPT_NODEFPERM */

#if defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NOVERSION))
    cdfs_flags |= MNT2_CDFS_OPT_NOVERSION;
#endif /* defined(MNT2_CDFS_OPT_NOVERSION) && defined(MNTTAB_OPT_NOVERSION) */

#if defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_RRIP))
    cdfs_flags |= MNT2_CDFS_OPT_RRIP;
#endif /* defined(MNT2_CDFS_OPT_RRIP) && defined(MNTTAB_OPT_RRIP) */
#if defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_NORRIP))
    cdfs_flags |= MNT2_CDFS_OPT_NORRIP;
#endif /* defined(MNT2_CDFS_OPT_NORRIP) && defined(MNTTAB_OPT_NORRIP) */

#if defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_GENS))
    cdfs_flags |= MNT2_CDFS_OPT_GENS;
#endif /* defined(MNT2_CDFS_OPT_GENS) && defined(MNTTAB_OPT_GENS) */
#if defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT)
  if (amu_hasmntopt(&mnt, MNTTAB_OPT_EXTATT))
    cdfs_flags |= MNT2_CDFS_OPT_EXTATT;
#endif /* defined(MNT2_CDFS_OPT_EXTATT) && defined(MNTTAB_OPT_EXTATT) */

  genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */

#ifdef HAVE_CDFS_ARGS_T_FLAGS
  cdfs_args.flags = cdfs_flags;
#endif /* HAVE_CDFS_ARGS_T_FLAGS */

#ifdef HAVE_CDFS_ARGS_T_ISO_FLAGS
  cdfs_args.iso_flags = genflags | cdfs_flags;
#endif /* HAVE_CDFS_ARGS_T_ISO_FLAGS */

#ifdef HAVE_CDFS_ARGS_T_ISO_PGTHRESH
  cdfs_args.iso_pgthresh = hasmntval(&mnt, MNTTAB_OPT_PGTHRESH);
#endif /* HAVE_CDFS_ARGS_T_ISO_PGTHRESH */

#ifdef HAVE_CDFS_ARGS_T_NORRIP
  /* XXX: need to provide norrip mount opt */
  cdfs_args.norrip = 0;		/* use Rock-Ridge Protocol extensions */
#endif /* HAVE_CDFS_ARGS_T_NORRIP */

#ifdef HAVE_CDFS_ARGS_T_SSECTOR
  /* XXX: need to provide ssector mount option */
  cdfs_args.ssector = 0;	/* use 1st session on disk */
#endif /* HAVE_CDFS_ARGS_T_SSECTOR */

#ifdef HAVE_CDFS_ARGS_T_FSPEC
  cdfs_args.fspec = fs_name;
#endif /* HAVE_CDFS_ARGS_T_FSPEC */

  /*
   * Call generic mount routine
   */
  retval = mount_fs(&mnt, genflags, (caddr_t) &cdfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);

  return retval;
}
예제 #2
0
static int
mount_pcfs(char *mntdir, char *fs_name, char *opts, int on_autofs)
{
  pcfs_args_t pcfs_args;
  mntent_t mnt;
  int flags;
#if defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK)
  int mask;
#endif /* defined(HAVE_PCFS_ARGS_T_MASK) || defined(HAVE_PCFS_ARGS_T_DIRMASK) */
#if defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID)
  char *str;
#endif /* defined(HAVE_PCFS_ARGS_T_UID) || defined(HAVE_PCFS_ARGS_T_UID) */

  /*
   * Figure out the name of the file system type.
   */
  MTYPE_TYPE type = MOUNT_TYPE_PCFS;

  memset((voidp) &pcfs_args, 0, sizeof(pcfs_args)); /* Paranoid */

  /*
   * Fill in the mount structure
   */
  memset((voidp) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = mntdir;
  mnt.mnt_fsname = fs_name;
  mnt.mnt_type = MNTTAB_TYPE_PCFS;
  mnt.mnt_opts = opts;

  flags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    flags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: flags=0x%x", (u_int) flags);

#ifdef HAVE_PCFS_ARGS_T_FSPEC
  pcfs_args.fspec = fs_name;
#endif /* HAVE_PCFS_ARGS_T_FSPEC */

#ifdef HAVE_PCFS_ARGS_T_MASK
  pcfs_args.mask = 0777;	/* this may be the msdos file modes */
  if ((mask = hasmntval(&mnt, MNTTAB_OPT_MASK)) > 0)
    pcfs_args.mask = mask;
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: mask=%o (octal)", (u_int) pcfs_args.mask);
#endif /* HAVE_PCFS_ARGS_T_MASK */

#ifdef HAVE_PCFS_ARGS_T_DIRMASK
  pcfs_args.dirmask = 0777;    /* this may be the msdos dir modes */
  if ((mask = hasmntval(&mnt, MNTTAB_OPT_DIRMASK)) > 0)
    pcfs_args.dirmask = mask;
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: dirmask=%o (octal)", (u_int) pcfs_args.dirmask);
#endif /* HAVE_PCFS_ARGS_T_DIRMASK */

#ifdef HAVE_PCFS_ARGS_T_UID
  pcfs_args.uid = 0;		/* default to root */
  if ((str = hasmntstr(&mnt, MNTTAB_OPT_USER)) != NULL) {
    struct passwd *pw;
    if ((pw = getpwnam(str)) != NULL)
      pcfs_args.uid = pw->pw_uid;
    else		 /* maybe used passed a UID number, not user name */
      pcfs_args.uid = atoi(str); /* atoi returns '0' if it failed */
    XFREE(str);
  }
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: uid=%d", (int) pcfs_args.uid);
#endif /* HAVE_PCFS_ARGS_T_UID */

#ifdef HAVE_PCFS_ARGS_T_GID
  pcfs_args.gid = 0;		/* default to wheel/root group */
  if ((str = hasmntstr(&mnt, MNTTAB_OPT_GROUP)) != NULL) {
    struct group *gr;
    if ((gr = getgrnam(str)) != NULL)
      pcfs_args.gid = gr->gr_gid;
    else		/* maybe used passed a GID number, not group name */
      pcfs_args.gid = atoi(str); /* atoi returns '0' if it failed */
    XFREE(str);
  }
  if (amuDebug(D_TRACE))
    plog(XLOG_DEBUG, "mount_pcfs: gid=%d", (int) pcfs_args.gid);
#endif /* HAVE_PCFS_ARGS_T_GID */

#ifdef HAVE_PCFS_ARGS_T_SECONDSWEST
  pcfs_args.secondswest = 0;	/* XXX: fill in correct values */
#endif /* HAVE_PCFS_ARGS_T_SECONDSWEST */
#ifdef HAVE_PCFS_ARGS_T_DSTTIME
  pcfs_args.dsttime = 0;	/* XXX: fill in correct values */
#endif /* HAVE_PCFS_ARGS_T_DSTTIME */

  /*
   * Call generic mount routine
   */
  return mount_fs(&mnt, flags, (caddr_t) & pcfs_args, 0, type, 0, NULL, mnttab_file_name, on_autofs);
}
예제 #3
0
int
mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname, int on_autofs)
{
  int error = 0;
#ifdef MOUNT_TABLE_ON_FILE
  char *zopts = NULL, *xopts = NULL;
  size_t l;
#endif /* MOUNT_TABLE_ON_FILE */
  char *mnt_dir = NULL;

#ifdef NEED_AUTOFS_SPACE_HACK
  char *old_mnt_dir = NULL;
  /* perform space hack */
  if (on_autofs) {
    old_mnt_dir = mnt->mnt_dir;
    mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir);
  } else
#endif /* NEED_AUTOFS_SPACE_HACK */
    mnt_dir = strdup(mnt->mnt_dir);

  dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)",
       mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);

again:
  error = MOUNT_TRAP(type, mnt, flags, mnt_data);

  if (error < 0) {
    plog(XLOG_ERROR, "'%s': mount: %m", mnt_dir);
    /*
     * The following code handles conditions which shouldn't
     * occur.  They are possible either because amd screws up
     * in preparing for the mount, or because some human
     * messed with the mount point.  Both have been known to
     * happen. -- stolcke 2/22/95
     */
    if (errno == EBUSY) {
      /*
       * Also, sometimes unmount isn't called, e.g., because
       * our mountlist is garbled.  This leaves old mount
       * points around which need to be removed before we
       * can mount something new in their place.
       */
      errno = umount_fs(mnt_dir, mnttabname, on_autofs);
      if (errno != 0)
	plog(XLOG_ERROR, "'%s': umount: %m", mnt_dir);
      else {
	plog(XLOG_WARNING, "extra umount required for '%s'", mnt_dir);
	error = MOUNT_TRAP(type, mnt, flags, mnt_data);
      }
    }
  }

  if (error < 0 && --retry > 0) {
    sleep(1);
    goto again;
  }

#ifdef NEED_AUTOFS_SPACE_HACK
  /* Undo space hack */
  if (on_autofs)
    mnt->mnt_dir = old_mnt_dir;
#endif /* NEED_AUTOFS_SPACE_HACK */

  if (error < 0) {
    error = errno;
    goto out;
  }

#ifdef MOUNT_TABLE_ON_FILE
  /*
   * Allocate memory for options:
   *        dev=..., vers={2,3}, proto={tcp,udp}
   */
  l = strlen(mnt->mnt_opts) + 48;
  zopts = (char *) xmalloc(l);

  /* copy standard options */
  xopts = mnt->mnt_opts;

  xstrlcpy(zopts, xopts, l);

# ifdef MNTTAB_OPT_DEV
  {
    /* add the extra dev= field to the mount table */
    struct stat stb;
    if (lstat(mnt_dir, &stb) == 0) {
      char optsbuf[48];
      if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
	xsnprintf(optsbuf, sizeof(optsbuf), "%s=%04lx",
		  MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
      else			/* e.g. System Vr4 */
	xsnprintf(optsbuf, sizeof(optsbuf), "%s=%08lx",
		  MNTTAB_OPT_DEV, (u_long) stb.st_dev);
      append_opts(zopts, l, optsbuf);
    }
  }
# endif /* MNTTAB_OPT_DEV */

# if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
  /*
   * add the extra vers={2,3} field to the mount table,
   * unless already specified by user
   */
   if (nfs_version == NFS_VERSION3 &&
       hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
     char optsbuf[48];
     xsnprintf(optsbuf, sizeof(optsbuf),
	       "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
     append_opts(zopts, l, optsbuf);
   }
# endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */

# ifdef MNTTAB_OPT_PROTO
  /*
   * add the extra proto={tcp,udp} field to the mount table,
   * unless already specified by user.
   */
  if (nfs_proto && !amu_hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
    char optsbuf[48];
    xsnprintf(optsbuf, sizeof(optsbuf), "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
    append_opts(zopts, l, optsbuf);
  }
# endif /* MNTTAB_OPT_PROTO */

  /* finally, store the options into the mount table structure */
  mnt->mnt_opts = zopts;

  /*
   * Additional fields in mntent_t
   * are fixed up here
   */
# ifdef HAVE_MNTENT_T_MNT_CNODE
  mnt->mnt_cnode = 0;
# endif /* HAVE_MNTENT_T_MNT_CNODE */

# ifdef HAVE_MNTENT_T_MNT_RO
  mnt->mnt_ro = (amu_hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
# endif /* HAVE_MNTENT_T_MNT_RO */

# ifdef HAVE_MNTENT_T_MNT_TIME
#  ifdef HAVE_MNTENT_T_MNT_TIME_STRING
  {				/* allocate enough space for a long */
    size_t l = 13 * sizeof(char);
    char *str = (char *) xmalloc(l);
    xsnprintf(str, l, "%ld", time((time_t *) NULL));
    mnt->mnt_time = str;
  }
#  else /* not HAVE_MNTENT_T_MNT_TIME_STRING */
  mnt->mnt_time = time((time_t *) NULL);
#  endif /* not HAVE_MNTENT_T_MNT_TIME_STRING */
# endif /* HAVE_MNTENT_T_MNT_TIME */

  write_mntent(mnt, mnttabname);

# ifdef MNTTAB_OPT_DEV
  if (xopts) {
    XFREE(mnt->mnt_opts);
    mnt->mnt_opts = xopts;
  }
# endif /* MNTTAB_OPT_DEV */
#endif /* MOUNT_TABLE_ON_FILE */

 out:
  XFREE(mnt_dir);
  return error;
}
예제 #4
0
/*
 * Fill in the many possible fields and flags of struct nfs_args.
 *
 * nap:		pre-allocated structure to fill in.
 * mntp:	mount entry structure (includes options)
 * genflags:	generic mount flags already determined
 * nfsncp:	(TLI only) netconfig entry for this NFS mount
 * ip_addr:	IP address of file server
 * nfs_version:	2, 3, (4 in the future), or 0 if unknown
 * nfs_proto:	"udp", "tcp", or NULL.
 * fhp:		file handle structure pointer
 * host_name:	name of remote NFS host
 * fs_name:	remote file system name to mount
 */
void
compute_nfs_args(nfs_args_t *nap,
		 mntent_t *mntp,
		 int genflags,
		 struct netconfig *nfsncp,
		 struct sockaddr_in *ip_addr,
		 u_long nfs_version,
		 char *nfs_proto,
		 am_nfs_handle_t *fhp,
		 char *host_name,
		 char *fs_name)
{
  /* initialize just in case */
  memset((voidp) nap, 0, sizeof(nfs_args_t));

  /* compute all of the NFS attribute-cache flags */
  compute_nfs_attrcache_flags(nap, mntp);

  /************************************************************************/
  /***	FILEHANDLE DATA AND LENGTH					***/
  /************************************************************************/
#ifdef HAVE_FS_NFS3
  if (nfs_version == NFS_VERSION3) {
# if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN)
    /*
     * Some systems (Irix/bsdi3) have a separate field in nfs_args for
     * the length of the file handle for NFS V3.  They insist that
     * the file handle set in nfs_args be plain bytes, and not
     * include the length field.
     */
    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data);
# else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3);
# endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
# ifdef MNT2_NFS_OPT_NFSV3
    nap->flags |= MNT2_NFS_OPT_NFSV3;
# endif /* MNT2_NFS_OPT_NFSV3 */
# ifdef MNT2_NFS_OPT_VER3
    nap->flags |= MNT2_NFS_OPT_VER3;
# endif /* MNT2_NFS_OPT_VER3 */
  } else
#endif /* HAVE_FS_NFS3 */
    NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);

#ifdef HAVE_NFS_ARGS_T_FHSIZE
# ifdef HAVE_FS_NFS3
  if (nfs_version == NFS_VERSION3)
    nap->fhsize = fhp->v3.am_fh3_length;
  else
# endif /* HAVE_FS_NFS3 */
    nap->fhsize = FHSIZE;
#endif /* HAVE_NFS_ARGS_T_FHSIZE */

  /* this is the version of the nfs_args structure, not of NFS! */
#ifdef HAVE_NFS_ARGS_T_FH_LEN
# ifdef HAVE_FS_NFS3
  if (nfs_version == NFS_VERSION3)
    nap->fh_len = fhp->v3.am_fh3_length;
  else
# endif /* HAVE_FS_NFS3 */
    nap->fh_len = FHSIZE;
#endif /* HAVE_NFS_ARGS_T_FH_LEN */

  /************************************************************************/
  /***	HOST NAME							***/
  /************************************************************************/
  /*
   * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a
   * struct nfs_args, or truncate our concocted "hostname:/path"
   * string prematurely.
   */
  NFS_HN_DREF(nap->hostname, host_name);
#ifdef MNT2_NFS_OPT_HOSTNAME
  nap->flags |= MNT2_NFS_OPT_HOSTNAME;
#endif /* MNT2_NFS_OPT_HOSTNAME */

  /************************************************************************/
  /***	IP ADDRESS OF REMOTE HOST					***/
  /************************************************************************/
  if (ip_addr) {
#ifdef HAVE_TRANSPORT_TYPE_TLI
    nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
#endif /* HAVE_TRANSPORT_TYPE_TLI */
    NFS_SA_DREF(nap, ip_addr);
  }

  /************************************************************************/
  /***	NFS PROTOCOL (UDP, TCP) AND VERSION				***/
  /************************************************************************/
#ifdef MNT2_NFS_OPT_TCP
  if (nfs_proto && STREQ(nfs_proto, "tcp"))
    nap->flags |= MNT2_NFS_OPT_TCP;
#endif /* MNT2_NFS_OPT_TCP */

#ifdef HAVE_NFS_ARGS_T_SOTYPE
  /* bsdi3 uses this */
  if (nfs_proto) {
    if (STREQ(nfs_proto, "tcp"))
      nap->sotype = SOCK_STREAM;
    else if (STREQ(nfs_proto, "udp"))
      nap->sotype = SOCK_DGRAM;
  }
#endif /* HAVE_NFS_ARGS_T_SOTYPE */

#ifdef HAVE_NFS_ARGS_T_PROTO
  nap->proto = 0;		/* bsdi3 sets this field to zero  */
# ifdef IPPROTO_TCP
  if (nfs_proto) {
    if (STREQ(nfs_proto, "tcp"))	/* AIX 4.2.x needs this */
      nap->proto = IPPROTO_TCP;
    else if (STREQ(nfs_proto, "udp"))
      nap->proto = IPPROTO_UDP;
  }
# endif /* IPPROTO_TCP */
#endif /* HAVE_NFS_ARGS_T_SOTYPE */

#ifdef HAVE_NFS_ARGS_T_VERSION
# ifdef NFS_ARGSVERSION
  nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
# endif /* NFS_ARGSVERSION */
# ifdef DG_MOUNT_NFS_VERSION
  nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
# endif /* DG_MOUNT_NFS_VERSION */
#endif /* HAVE_NFS_ARGS_VERSION */

  /************************************************************************/
  /***	OTHER NFS SOCKET RELATED OPTIONS AND FLAGS			***/
  /************************************************************************/
#ifdef MNT2_NFS_OPT_NOCONN
  /* check if user specified to use unconnected or connected sockets */
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
    nap->flags |= MNT2_NFS_OPT_NOCONN;
  else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
    nap->flags &= ~MNT2_NFS_OPT_NOCONN;
  else {
    /*
     * Some OSs want you to set noconn always.  Some want you to always turn
     * it off.  Others want you to turn it on/off only if NFS V.3 is used.
     * And all of that changes from revision to another.  This is
     * particularly true of OpenBSD, NetBSD, and FreeBSD.  So, rather than
     * attempt to auto-detect this, I'm forced to "fix" it in the individual
     * conf/nfs_prot/nfs_prot_*.h files.
     */
# ifdef USE_UNCONNECTED_NFS_SOCKETS
    if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) {
      nap->flags |= MNT2_NFS_OPT_NOCONN;
      plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)");
    }
# endif /* USE_UNCONNECTED_NFS_SOCKETS */
# ifdef USE_CONNECTED_NFS_SOCKETS
    if (nap->flags & MNT2_NFS_OPT_NOCONN) {
      nap->flags &= ~MNT2_NFS_OPT_NOCONN;
      plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)");
    }
# endif /* USE_CONNECTED_NFS_SOCKETS */
  }
#endif /* MNT2_NFS_OPT_NOCONN */

#ifdef MNT2_NFS_OPT_RESVPORT
# ifdef MNTTAB_OPT_RESVPORT
  if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
    nap->flags |= MNT2_NFS_OPT_RESVPORT;
# else /* not MNTTAB_OPT_RESVPORT */
  nap->flags |= MNT2_NFS_OPT_RESVPORT;
# endif /* not MNTTAB_OPT_RESVPORT */
#endif /* MNT2_NFS_OPT_RESVPORT */

  /************************************************************************/
  /***	OTHER FLAGS AND OPTIONS						***/
  /************************************************************************/

#ifdef HAVE_TRANSPORT_TYPE_TLI
  /* set up syncaddr field */
  nap->syncaddr = (struct netbuf *) NULL;

  /* set up knconf field */
  if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
    plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
    going_down(1);
  }
  /* update the flags field for knconf */
  nap->flags |= MNT2_NFS_OPT_KNCONF;
#endif /* HAVE_TRANSPORT_TYPE_TLI */

#ifdef MNT2_NFS_OPT_FSNAME
  nap->fsname = fs_name;
  nap->flags |= MNT2_NFS_OPT_FSNAME;
#endif /* MNT2_NFS_OPT_FSNAME */

  nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
#ifdef MNT2_NFS_OPT_RSIZE
  if (nap->rsize)
    nap->flags |= MNT2_NFS_OPT_RSIZE;
#endif /* MNT2_NFS_OPT_RSIZE */
  if (nfs_version == NFS_VERSION && nap->rsize > 8192)
    nap->rsize = 8192;

  nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
#ifdef MNT2_NFS_OPT_WSIZE
  if (nap->wsize)
    nap->flags |= MNT2_NFS_OPT_WSIZE;
#endif /* MNT2_NFS_OPT_WSIZE */
  if (nfs_version == NFS_VERSION && nap->wsize > 8192)
    nap->wsize = 8192;

  nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
#ifdef MNT2_NFS_OPT_TIMEO
  if (nap->timeo)
    nap->flags |= MNT2_NFS_OPT_TIMEO;
#endif /* MNT2_NFS_OPT_TIMEO */

  nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS);
#ifdef MNT2_NFS_OPT_RETRANS
  if (nap->retrans)
    nap->flags |= MNT2_NFS_OPT_RETRANS;
#endif /* MNT2_NFS_OPT_RETRANS */

#ifdef MNT2_NFS_OPT_BIODS
  if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
    nap->flags |= MNT2_NFS_OPT_BIODS;
#endif /* MNT2_NFS_OPT_BIODS */

#ifdef MNT2_NFS_OPT_SOFT
  if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
    nap->flags |= MNT2_NFS_OPT_SOFT;
#endif /* MNT2_NFS_OPT_SOFT */

#ifdef MNT2_NFS_OPT_SPONGY
  if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
    nap->flags |= MNT2_NFS_OPT_SPONGY;
    if (nap->flags & MNT2_NFS_OPT_SOFT) {
      plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
      nap->flags &= ~MNT2_NFS_OPT_SOFT;
    }
  }
#endif /* MNT2_NFS_OPT_SPONGY */

#if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
  /* Ultrix has separate generic and NFS ro flags */
  if (genflags & MNT2_GEN_OPT_RONLY)
    nap->flags |= MNT2_NFS_OPT_RONLY;
#endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */

#ifdef MNTTAB_OPT_INTR
  if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
    /*
     * Either turn on the "allow interrupts" option, or
     * turn off the "disallow interrupts" option"
     */
# ifdef MNT2_NFS_OPT_INTR
    nap->flags |= MNT2_NFS_OPT_INTR;
# endif /* MNT2_NFS_OPT_INTR */
# ifdef MNT2_NFS_OPT_NOINTR
    nap->flags &= ~MNT2_NFS_OPT_NOINTR;
# endif /* MNT2_NFS_OPT_NOINTR */
# ifdef MNT2_NFS_OPT_INT
    nap->flags |= MNT2_NFS_OPT_INT;
# endif /* MNT2_NFS_OPT_INT */
# ifdef MNT2_NFS_OPT_NOINT
    nap->flags &= ~MNT2_NFS_OPT_NOINT;
# endif /* MNT2_NFS_OPT_NOINT */
#endif /* MNTTAB_OPT_INTR */

#ifdef MNTTAB_OPT_NODEVS
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
    nap->flags |= MNT2_NFS_OPT_NODEVS;
#endif /* MNTTAB_OPT_NODEVS */

#ifdef MNTTAB_OPT_COMPRESS
  if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
    nap->flags |= MNT2_NFS_OPT_COMPRESS;
#endif /* MNTTAB_OPT_COMPRESS */

#ifdef MNTTAB_OPT_PRIVATE	/* mount private, single-client tree */
  if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
    nap->flags |= MNT2_NFS_OPT_PRIVATE;
#endif /* MNTTAB_OPT_PRIVATE */

#ifdef MNTTAB_OPT_SYMTTL	/* symlink cache time-to-live */
  if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
    nap->flags |= MNT2_NFS_OPT_SYMTTL;
#endif /* MNTTAB_OPT_SYMTTL */

#ifdef MNT2_NFS_OPT_PGTHRESH	/* paging threshold */
  if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
    nap->flags |= MNT2_NFS_OPT_PGTHRESH;
#endif /* MNT2_NFS_OPT_PGTHRESH */

#if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
    nap->flags |= MNT2_NFS_OPT_NOCTO;
#endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */

#if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
    nap->flags |= MNT2_NFS_OPT_POSIX;
# ifdef HAVE_NFS_ARGS_T_PATHCONF
    nap->pathconf = NULL;
# endif /* HAVE_NFS_ARGS_T_PATHCONF */
  }
#endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */

#if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL)
    nap->flags |= MNT2_NFS_OPT_PROPLIST;
#endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */

#if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
  nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
  if (nap->maxgrouplist != 0)
    nap->flags |= MNT2_NFS_OPT_MAXGRPS;
#endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */

#if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL)
    nap->flags |= MNT2_NFS_OPT_NONLM;
#endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */

#if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE)
  if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL)
    nap->flags |= MNT2_NFS_OPT_XLATECOOKIE;
#endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */

#ifdef HAVE_NFS_ARGS_T_OPTSTR
  nap->optstr = mntp->mnt_opts;
#endif /* HAVE_NFS_ARGS_T_OPTSTR */

  /************************************************************************/
  /***	FINAL ACTIONS							***/
  /************************************************************************/

#ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
  /* Ultrix stores generic flags in nfs_args.gfs_flags. */
  nap->gfs_flags = genflags;
#endif /* HAVE_NFS_ARGS_T_FLAGS */

  return;			/* end of compute_nfs_args() function */
}
예제 #5
0
/*
 * Mount an automounter directory.
 * The automounter is connected into the system
 * as a user-level NFS server.  mount_amfs_toplvl constructs
 * the necessary NFS parameters to be given to the
 * kernel so that it will talk back to us.
 *
 * NOTE: automounter mounts in themselves are using NFS Version 2.
 */
static int
mount_amfs_toplvl(char *dir, char *opts)
{
    char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
    int retry, error, genflags;
    mntent_t mnt;
    nfs_args_t nfs_args;
    am_nfs_fh *fhp;
    am_nfs_handle_t anh;
    MTYPE_TYPE type = MOUNT_TYPE_NFS;
#ifndef HAVE_TRANSPORT_TYPE_TLI
    u_short port;
    struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    memset((voidp) &mnt, 0, sizeof(mnt));
    mnt.mnt_dir = dir;
    mnt.mnt_fsname = pid_fsname;
    mnt.mnt_opts = opts;

    /*
     * Make sure that amd's top-level NFS mounts are hidden by default
     * from df.
     * If they don't appear to support the either the "ignore" mnttab
     * option entry, or the "auto" one, set the mount type to "nfs".
     */
    mnt.mnt_type = HIDE_MOUNT_TYPE;

    retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
    if (retry <= 0)
        retry = 2;			/* XXX */

    /*
     * SET MOUNT ARGS
     */
    /*
     * get fhandle of remote path for automount point
     */
    fhp = root_fh(dir);
    if (!fhp) {
        plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
        return EINVAL;
    }

#ifndef HAVE_TRANSPORT_TYPE_TLI
    /*
     * Create sockaddr to point to the local machine.  127.0.0.1
     * is not used since that will not work in HP-UX clusters and
     * this is no more expensive.
     */
    memset((voidp) &sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr = myipaddr;
    port = hasmntval(&mnt, MNTTAB_OPT_PORT);
    if (port) {
        sin.sin_port = htons(port);
    } else {
        plog(XLOG_ERROR, "no port number specified for %s", dir);
        return EINVAL;
    }
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*
     * Make a ``hostname'' string for the kernel
     */
    sprintf(fs_hostname, "pid%ld@%s:%s",
            (long) (foreground ? am_mypid : getppid()),
            am_get_hostname(),
            dir);
    /*
     * Most kernels have a name length restriction (64 bytes)...
     */
    if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
        strcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..");
#ifdef HOSTNAMESZ
    /*
     * ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
     * If you need to get the definition for HOSTNAMESZ found, you may
     * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
     */
    if (strlen(fs_hostname) >= HOSTNAMESZ)
        strcpy(fs_hostname + HOSTNAMESZ - 3, "..");
#endif /* HOSTNAMESZ */

    /*
     * Finally we can compute the mount genflags set above,
     * and add any automounter specific flags.
     */
    genflags = compute_mount_flags(&mnt);
    genflags |= compute_automounter_mount_flags(&mnt);

    /* setup the many fields and flags within nfs_args */
    memmove(&anh.v2.fhs_fh, fhp, sizeof(*fhp));
#ifdef HAVE_TRANSPORT_TYPE_TLI
    compute_nfs_args(&nfs_args,
                     &mnt,
                     genflags,
                     nfsncp,
                     NULL,	/* remote host IP addr is set below */
                     NFS_VERSION,	/* version 2 */
                     "udp",
                     &anh,
                     fs_hostname,
                     pid_fsname);
    /*
     * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
     * be done using the normal mechanism of compute_nfs_args(), because
     * that one will allocate a new address and use NFS_SA_DREF() to copy
     * parts to it, while assuming that the ip_addr passed is always
     * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
     * because they define a special macro HOST_SELF which is DIFFERENT
     * than localhost (127.0.0.1)!
     */
    nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
    compute_nfs_args(&nfs_args,
                     &mnt,
                     genflags,
                     &sin,
                     NFS_VERSION,	/* version 2 */
                     "udp",
                     &anh,
                     fs_hostname,
                     pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*************************************************************************
     * NOTE: while compute_nfs_args() works ok for regular NFS mounts	   *
     * the toplvl one is not, and so some options must be corrected by hand  *
     * more carefully, *after* compute_nfs_args() runs.			   *
     *************************************************************************/
    compute_automounter_nfs_args(&nfs_args, &mnt);

    /* This is it!  Here we try to mount amd on its mount points */
#ifdef DEBUG
    amuDebug(D_TRACE) {
        print_nfs_args(&nfs_args, 0);
        plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
    }
#endif /* DEBUG */
    error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type,
                     0, NULL, mnttab_file_name);

#ifdef HAVE_TRANSPORT_TYPE_TLI
    free_knetconfig(nfs_args.knconf);
    /*
     * local automounter mounts do not allocate a special address, so
     * no need to XFREE(nfs_args.addr) under TLI.
     */
#endif /* HAVE_TRANSPORT_TYPE_TLI */

    return error;
}
예제 #6
0
파일: hlfsd.c 프로젝트: AzerTyQsdF/osx
int
main(int argc, char *argv[])
{
  char *dot;
  char *mntopts = (char *) NULL;
  char hostpid_fs[MAXHOSTNAMELEN + 1 + 16];	/* room for ":(pid###)" */
  char progpid_fs[PROGNAMESZ + 1 + 11];		/* room for ":pid" */
  char preopts[128];
  char *progname;
  int forcecache = 0;
  int forcefast = 0;
  int genflags = 0;
  int opt, ret;
  int opterrs = 0;
  int retry;
  int soNFS;			/* NFS socket */
  int s = -99;
  mntent_t mnt;
  nfs_args_t nfs_args;
  am_nfs_handle_t anh;
  struct dirent *direntry;
  struct group *grp;
  struct stat stmodes;
  DIR *mountdir;
  MTYPE_TYPE type = MOUNT_TYPE_NFS;

#ifdef HAVE_SIGACTION
  struct sigaction sa;
#endif /* not HAVE_SIGACTION */

#ifndef HAVE_TRANSPORT_TYPE_TLI
  struct sockaddr_in localsocket;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */


  /* get program name and truncate so we don't overflow progpid_fs */

  if ((progname = strrchr(argv[0], '/')) != NULL)
    progname++;
  else
    progname = argv[0];
  if ((int) strlen(progname) > PROGNAMESZ) /* truncate to reasonable size */
    progname[PROGNAMESZ] = '\0';
  am_set_progname(progname);

  while ((opt = getopt(argc, argv, "a:c:CD:fg:hi:l:no:pP:x:v")) != -1)
    switch (opt) {

    case 'a':
      if (!optarg || optarg[0] != '/') {
	printf("%s: invalid directory for -a: %s\n",
	       am_get_progname(), optarg);
	exit(3);
      }
      alt_spooldir = optarg;
      break;

    case 'c':
      if (!atoi(optarg)) {
	printf("%s: invalid interval for -c: %s\n",
	       am_get_progname(), optarg);
	exit(3);
      }
      cache_interval = atoi(optarg);
      break;

    case 'C':
      forcecache++;
      break;

    case 'f':
      forcefast++;
      break;

    case 'g':
      hlfs_group = optarg;
      break;

    case 'i':
      if (!atoi(optarg)) {
	printf("%s: invalid interval for -i: %s\n",
	       am_get_progname(), optarg);
	exit(3);
      }
      reloadinterval.it_interval.tv_sec = atoi(optarg);
      reloadinterval.it_value.tv_sec = atoi(optarg);
      break;

    case 'l':
      logfile = optarg;
      break;

    case 'n':
      noverify++;
      break;

    case 'o':
      mntopts = optarg;
      break;

    case 'p':
      printpid++;
      break;

    case 'P':
      passwdfile = optarg;
      break;

    case 'v':
      fprintf(stderr, "%s\n", HLFSD_VERSION);
      exit(0);

    case 'x':
      opterrs += switch_option(optarg);
      break;

    case 'D':
#ifdef DEBUG
      opterrs += debug_option(optarg);
#else /* not DEBUG */
      fprintf(stderr, "%s: not compiled with DEBUG -- sorry.\n", am_get_progname());
#endif /* not DEBUG */
      break;

    case 'h':
    case '?':
      opterrs++;
    }

  /* set some default debugging options */
  if (xlog_level_init == ~0)
    switch_option("");
  /* need my pid before any dlog/plog */
  am_set_mypid();
#ifdef DEBUG
  switch_option("debug");
#endif /* DEBUG */

/*
 * Terminate if did not ask to forcecache (-C) and hlfsd would not be able
 * to set the minimum cache intervals.
 */
#if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN)
  if (!forcecache) {
    fprintf(stderr, "%s: will not be able to turn off attribute caches.\n", am_get_progname());
    exit(1);
  }
#endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_NFS_ARGS_T_ACREGMIN) */


  switch (argc - optind) {
  case 2:
    home_subdir = argv[optind + 1];
  case 1:
    dir_name = argv[optind];
  case 0:
    break;
  default:
    opterrs++;
  }

  if (opterrs)
    usage();

  /* ensure that only root can run hlfsd */
  if (geteuid()) {
    fprintf(stderr, "hlfsd can only be run as root\n");
    exit(1);
  }
  setbuf(stdout, (char *) NULL);
  umask(0);

  /* find gid for hlfs_group */
  if ((grp = getgrnam(hlfs_group)) == (struct group *) NULL) {
    fprintf(stderr, "%s: cannot get gid for group \"%s\".\n",
	    am_get_progname(), hlfs_group);
  } else {
    hlfs_gid = grp->gr_gid;
  }

  /* get hostname for logging and open log before we reset umask */
  gethostname(hostname, sizeof(hostname));
  hostname[sizeof(hostname) - 1] = '\0';
  if ((dot = strchr(hostname, '.')) != NULL)
    *dot = '\0';
  orig_umask = umask(0);
  if (logfile)
    switch_to_logfile(logfile, orig_umask);

#if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE)
  if (debug_flags & D_MTAB)
    dlog("-D mtab option ignored");
#endif /* defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) */

  /* avoid hanging on other NFS servers if started elsewhere */
  if (chdir("/") < 0)
    fatal("cannot chdir to /: %m");

  if (geteuid() != 0)
    fatal("must be root to mount filesystems");

  /*
   * dir_name must match "^(/.*)/([^/]+)$", and is split at last '/' with
   * slinkname = `basename $dir_name` - requires dir_name be writable
   */

  if (dir_name[0] != '/'
      || ((slinkname = strrchr(dir_name, '/')), *slinkname++ = '\0',
	  (dir_name[0] == '\0' || slinkname[0] == '\0'))) {
    if (slinkname)
      *--slinkname = '/';
    printf("%s: invalid mount directory/link %s\n",
	   am_get_progname(), dir_name);
    exit(3);
  }

  clock_valid = 0;		/* invalidate logging clock */

  if (!forcefast) {
    /* make sure mount point exists and is at least mode 555 */
    if (stat(dir_name, &stmodes) < 0)
      if (errno != ENOENT || mkdirs(dir_name, 0555) < 0
	  || stat(dir_name, &stmodes) < 0)
	fatalerror(dir_name);

    if ((stmodes.st_mode & 0555) != 0555) {
      fprintf(stderr, "%s: directory %s not read/executable\n",
	      am_get_progname(), dir_name);
      plog(XLOG_WARNING, "directory %s not read/executable",
	   dir_name);
    }

    /* warn if extraneous stuff will be hidden by mount */
    if ((mountdir = opendir(dir_name)) == NULL)
      fatalerror(dir_name);

    while ((direntry = readdir(mountdir)) != NULL) {
      if (!NSTREQ(".", direntry->d_name, NAMLEN(direntry)) &&
	  !NSTREQ("..", direntry->d_name, NAMLEN(direntry)) &&
	  !NSTREQ(slinkname, direntry->d_name, NAMLEN(direntry)))
	break;
    }

    if (direntry != NULL) {
      fprintf(stderr, "%s: %s/%s will be hidden by mount\n",
	      am_get_progname(), dir_name, direntry->d_name);
      plog(XLOG_WARNING, "%s/%s will be hidden by mount\n",
	   dir_name, direntry->d_name);
    }
    closedir(mountdir);

    /* make sure alternate spool dir exists */
    if ((errno = mkdirs(alt_spooldir, OPEN_SPOOLMODE))) {
      fprintf(stderr, "%s: cannot create alternate dir ",
	      am_get_progname());
      perror(alt_spooldir);
      plog(XLOG_ERROR, "cannot create alternate dir %s: %m",
	   alt_spooldir);
    }
    chmod(alt_spooldir, OPEN_SPOOLMODE);

    /* create failsafe link to alternate spool directory */
    slinkname[-1] = '/';	/* unsplit dir_name to include link */
    if (lstat(dir_name, &stmodes) == 0 &&
	(stmodes.st_mode & S_IFMT) != S_IFLNK) {
      fprintf(stderr, "%s: failsafe %s not a symlink\n",
	      am_get_progname(), dir_name);
      plog(XLOG_WARNING, "failsafe %s not a symlink\n",
	   dir_name);
    } else {
      unlink(dir_name);

      if (symlink(alt_spooldir, dir_name) < 0) {
	fprintf(stderr,
		"%s: cannot create failsafe symlink %s -> ",
		am_get_progname(), dir_name);
	perror(alt_spooldir);
	plog(XLOG_WARNING,
	     "cannot create failsafe symlink %s -> %s: %m",
	     dir_name, alt_spooldir);
      }
    }

    slinkname[-1] = '\0';	/* resplit dir_name */
  } /* end of "if (!forcefast) {" */

  /*
   * Register hlfsd as an nfs service with the portmapper.
   */
#ifdef HAVE_TRANSPORT_TYPE_TLI
  ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
#else /* not HAVE_TRANSPORT_TYPE_TLI */
  ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */
  if (ret != 0)
    fatal("cannot create NFS service");

#ifdef HAVE_SIGACTION
  sa.sa_handler = proceed;
  sa.sa_flags = 0;
  sigemptyset(&(sa.sa_mask));
  sigaddset(&(sa.sa_mask), SIGUSR2);
  sigaction(SIGUSR2, &sa, NULL);
#else /* not HAVE_SIGACTION */
  signal(SIGUSR2, proceed);
#endif /* not HAVE_SIGACTION */

  plog(XLOG_INFO, "Initializing hlfsd...");
  hlfsd_init();			/* start up child (forking) to run svc_run */

#ifdef HAVE_SIGACTION
  sa.sa_handler = reaper;
  sa.sa_flags = 0;
  sigemptyset(&(sa.sa_mask));
  sigaddset(&(sa.sa_mask), SIGCHLD);
  sigaction(SIGCHLD, &sa, NULL);
#else /* not HAVE_SIGACTION */
  signal(SIGCHLD, reaper);
#endif /* not HAVE_SIGACTION */

#ifdef DEBUG
  /*
   * In the parent, if -D nodaemon (or -D daemon) , we don't need to
   * set this signal handler.
   */
  amuDebug(D_DAEMON) {
#endif /* DEBUG */
    /* XXX: port to use pure svr4 signals */
    s = -99;
    while (stoplight != SIGUSR2) {
      plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight);
      s = sigpause(0);		/* wait for child to set up */
      sleep(1);
    }
#ifdef DEBUG
  }
#endif /* DEBUG */

  /*
   * setup options to mount table (/etc/{mtab,mnttab}) entry
   */
  sprintf(hostpid_fs, "%s:(pid%d)", hostname, masterpid);
  memset((char *) &mnt, 0, sizeof(mnt));
  mnt.mnt_dir = dir_name;	/* i.e., "/mail" */
  mnt.mnt_fsname = hostpid_fs;
  if (mntopts) {
    mnt.mnt_opts = mntopts;
  } else {
    strcpy(preopts, default_mntopts);
    /*
     * Turn off all kinds of attribute and symlink caches as
     * much as possible.  Also make sure that mount does not
     * show up to df.
     */
#ifdef MNTTAB_OPT_INTR
    strcat(preopts, ",");
    strcat(preopts, MNTTAB_OPT_INTR);
#endif /* MNTTAB_OPT_INTR */
#ifdef MNTTAB_OPT_IGNORE
    strcat(preopts, ",");
    strcat(preopts, MNTTAB_OPT_IGNORE);
#endif /* MNTTAB_OPT_IGNORE */
#ifdef MNT2_GEN_OPT_CACHE
    strcat(preopts, ",nocache");
#endif /* MNT2_GEN_OPT_CACHE */
#ifdef MNT2_NFS_OPT_SYMTTL
    strcat(preopts, ",symttl=0");
#endif /* MNT2_NFS_OPT_SYMTTL */
    mnt.mnt_opts = preopts;
  }

  /*
   * Make sure that amd's top-level NFS mounts are hidden by default
   * from df.
   * If they don't appear to support the either the "ignore" mnttab
   * option entry, or the "auto" one, set the mount type to "nfs".
   */
#ifdef HIDE_MOUNT_TYPE
  mnt.mnt_type = HIDE_MOUNT_TYPE;
#else /* not HIDE_MOUNT_TYPE */
  mnt.mnt_type = "nfs";
#endif /* not HIDE_MOUNT_TYPE */
  /* some systems don't have a mount type, but a mount flag */

#ifndef HAVE_TRANSPORT_TYPE_TLI
  amu_get_myaddress(&localsocket.sin_addr);
  localsocket.sin_family = AF_INET;
  localsocket.sin_port = htons(nfsxprt->xp_port);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

  /*
   * Update hostname field.
   * Make some name prog:pid (i.e., hlfsd:174) for hostname
   */
  sprintf(progpid_fs, "%s:%d", am_get_progname(), masterpid);

  /* Most kernels have a name length restriction. */
  if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN)
    strcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..");

  genflags = compute_mount_flags(&mnt);

  retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
  if (retry <= 0)
    retry = 1;			/* XXX */

  memmove(&anh.v2.fhs_fh, root_fhp, sizeof(*root_fhp));
#ifdef HAVE_TRANSPORT_TYPE_TLI
  compute_nfs_args(&nfs_args,
		   &mnt,
		   genflags,
		   nfsncp,
		   NULL,	/* remote host IP addr is set below */
		   NFS_VERSION,	/* version 2 */
		   "udp",	/* XXX: shouldn't this be "udp"? */
		   &anh,
		   progpid_fs,	/* host name for kernel */
		   hostpid_fs); /* filesystem name for kernel */
  /*
   * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
   * be done using the normal mechanism of compute_nfs_args(), because
   * that one will allocate a new address and use NFS_SA_DREF() to copy
   * parts to it, while assuming that the ip_addr passed is always
   * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
   * because they define a special macro HOST_SELF which is DIFFERENT
   * than localhost (127.0.0.1)!
   */
  nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
  compute_nfs_args(&nfs_args,
		   &mnt,
		   genflags,
		   NULL,
		   &localsocket,
		   NFS_VERSION, /* version 2 */
		   "udp",	/* XXX: shouldn't this be "udp"? */
		   &anh,
		   progpid_fs,	/* host name for kernel */
		   hostpid_fs); /* filesystem name for kernel */
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

  /*************************************************************************
   * NOTE: while compute_nfs_args() works ok for regular NFS mounts	   *
   * the toplvl one is not, and so some options must be corrected by hand  *
   * more carefully, *after* compute_nfs_args() runs.			   *
   *************************************************************************/
  compute_automounter_nfs_args(&nfs_args, &mnt);

  clock_valid = 0;		/* invalidate logging clock */

/*
 * The following code could be cleverly ifdef-ed, but I duplicated the
 * mount_fs call three times for simplicity and readability.
 */
#ifdef DEBUG
/*
 * For some reason, this mount may have to be done in the background, if I am
 * using -D nodebug.  I suspect that the actual act of mounting requires
 * calling to hlfsd itself to invoke one or more of its nfs calls, to stat
 * /mail.  That means that even if you say -D nodaemon, at least the mount
 * of hlfsd itself on top of /mail will be done in the background.
 * The other alternative I have is to run svc_run, but set a special
 * signal handler to perform the mount in N seconds via some alarm.
 *      -Erez Zadok.
 */
  amuDebug(D_DAEMON) {	/* asked for -D daemon */
    plog(XLOG_INFO, "parent NFS mounting hlfsd service points");
    if (mount_fs2(&mnt, dir_name, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0)
      fatal("nfsmount: %m");
  } else {			/* asked for -D nodaemon */
    if (fork() == 0) {		/* child runs mount */
예제 #7
0
void
am_mounted(am_node *mp)
{
  mntfs *mf = mp->am_mnt;

  mf_mounted(mf);

  /*
   * Patch up path for direct mounts
   */
  if (mp->am_parent && mp->am_parent->am_mnt->mf_ops == &amfs_direct_ops)
    mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");

  /*
   * Check whether this mount should be cached permanently
   */
  if (mf->mf_ops->fs_flags & FS_NOTIMEOUT) {
    mp->am_flags |= AMF_NOTIMEOUT;
  } else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
    mp->am_flags |= AMF_NOTIMEOUT;
  } else {
    mntent_t mnt;
    if (mf->mf_mopts) {
      mnt.mnt_opts = mf->mf_mopts;
      if (hasmntopt(&mnt, "nounmount"))
	mp->am_flags |= AMF_NOTIMEOUT;
      if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
	mp->am_timeo = gopt.am_timeo;
    }
  }

  /*
   * If this node is a symlink then
   * compute the length of the returned string.
   */
  if (mp->am_fattr.na_type == NFLNK)
    mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);

  /*
   * Record mount time
   */
  mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime();
  new_ttl(mp);

  /*
   * Update mtime of parent node
   */
  if (mp->am_parent && mp->am_parent->am_mnt)
    mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime;

  /*
   * Now, if we can, do a reply to our NFS client here
   * to speed things up.
   */
  quick_reply(mp, 0);

  /*
   * Update stats
   */
  amd_stats.d_mok++;
}
예제 #8
0
파일: autil.c 프로젝트: AzerTyQsdF/osx
void
am_mounted(am_node *mp)
{
  mntfs *mf = mp->am_mnt;

  mf_mounted(mf);

#ifdef HAVE_FS_AUTOFS
  if (mf->mf_flags & MFF_AUTOFS)
    autofs_mounted(mp);
#endif /* HAVE_FS_AUTOFS */

  /*
   * Patch up path for direct mounts
   */
  if (mp->am_parent && mp->am_parent->am_mnt->mf_fsflags & FS_DIRECT)
    mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");

  /*
   * Check whether this mount should be cached permanently
   */
  if (mf->mf_fsflags & FS_NOTIMEOUT) {
    mp->am_flags |= AMF_NOTIMEOUT;
  } else if (mf->mf_mount[1] == '\0' && mf->mf_mount[0] == '/') {
    mp->am_flags |= AMF_NOTIMEOUT;
  } else {
    mntent_t mnt;
    if (mf->mf_mopts) {
      mnt.mnt_opts = mf->mf_mopts;
      if (hasmntopt(&mnt, "nounmount"))
	mp->am_flags |= AMF_NOTIMEOUT;
      if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
	mp->am_timeo = gopt.am_timeo;
    }
  }

  /*
   * If this node is a symlink then
   * compute the length of the returned string.
   */
  if (mp->am_fattr.na_type == NFLNK)
    mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mp->am_mnt->mf_mount);

  /*
   * Record mount time
   */
  mp->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime = clocktime();
  new_ttl(mp);

  /*
   * Update mtime of parent node
   */
  if (mp->am_parent && mp->am_parent->am_mnt)
    mp->am_parent->am_fattr.na_mtime.nt_seconds = mp->am_stats.s_mtime;

  /*
   * This is ugly, but essentially unavoidable
   * Sublinks must be treated separately as type==link
   * when the base type is different.
   */
  if (mp->am_link && mp->am_mnt->mf_ops != &amfs_link_ops)
    amfs_link_ops.mount_fs(mp, mp->am_mnt);

#ifdef HAVE_FS_AUTOFS
  if (mp->am_flags & AMF_AUTOFS)
    autofs_mount_succeeded(mp);
  else
#endif /* HAVE_FS_AUTOFS */
    /*
     * Now, if we can, do a reply to our NFS client here
     * to speed things up.
     */
    nfs_quick_reply(mp, 0);

  /*
   * Update stats
   */
  amd_stats.d_mok++;
}
예제 #9
0
파일: mount_fs.c 프로젝트: AzerTyQsdF/osx
int
mount_fs2(mntent_t *mnt, char *real_mntdir, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname)
{
  int error = 0;
#ifdef MOUNT_TABLE_ON_FILE
# ifdef MNTTAB_OPT_DEV
  struct stat stb;
# endif /* MNTTAB_OPT_DEV */
  char *zopts = NULL, *xopts = NULL;
# if defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO)
  char optsbuf[48];
# endif /* defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO) */
#endif /* MOUNT_TABLE_ON_FILE */

  char *old_mnt_dir;

  old_mnt_dir = mnt->mnt_dir;
  mnt->mnt_dir = real_mntdir;

  amuDebug(D_FULL) {
    dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)",
	 mnt->mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
  }

again:
  clock_valid = 0;

  error = MOUNT_TRAP(type, mnt, flags, mnt_data);

  if (error < 0) {
    plog(XLOG_ERROR, "%s: mount: %m", mnt->mnt_dir);
    /*
     * The following code handles conditions which shouldn't
     * occur.  They are possible either because amd screws up
     * in preparing for the mount, or because some human
     * messed with the mount point.  Both have been known to
     * happen. -- stolcke 2/22/95
     */
    if (errno == ENOENT) {
      /*
       * Occasionally the mount point vanishes, probably
       * due to some race condition.  Just recreate it
       * as necessary.
       */
      errno = mkdirs(mnt->mnt_dir, 0555);
      if (errno != 0 && errno != EEXIST)
	plog(XLOG_ERROR, "'%s': mkdirs: %m", mnt->mnt_dir);
      else {
	plog(XLOG_WARNING, "extra mkdirs required for '%s'",
	     mnt->mnt_dir);
	error = MOUNT_TRAP(type, mnt, flags, mnt_data);
      }
    } else if (errno == EBUSY) {
      /*
       * Also, sometimes unmount isn't called, e.g., because
       * our mountlist is garbled.  This leaves old mount
       * points around which need to be removed before we
       * can mount something new in their place.
       */
      errno = umount_fs2(old_mnt_dir, mnt->mnt_dir, mnttabname);
      if (errno != 0)
	plog(XLOG_ERROR, "'%s': umount: %m", mnt->mnt_dir);
      else {
	plog(XLOG_WARNING, "extra umount required for '%s'",
	     mnt->mnt_dir);
	error = MOUNT_TRAP(type, mnt, flags, mnt_data);
      }
    }
  }

  if (error < 0 && --retry > 0) {
    sleep(1);
    goto again;
  }
  if (error < 0) {
    return errno;
  }

#ifdef MOUNT_TABLE_ON_FILE
  /*
   * Allocate memory for options:
   *        dev=..., vers={2,3}, proto={tcp,udp}
   */
  zopts = (char *) xmalloc(strlen(mnt->mnt_opts) + 48);

  /* copy standard options */
  xopts = mnt->mnt_opts;

  strcpy(zopts, xopts);

# ifdef MNTTAB_OPT_DEV
  /* add the extra dev= field to the mount table */
  if (lstat(mnt->mnt_dir, &stb) == 0) {
    if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
      sprintf(optsbuf, "%s=%04lx",
	      MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
    else			/* e.g. System Vr4 */
      sprintf(optsbuf, "%s=%08lx",
	      MNTTAB_OPT_DEV, (u_long) stb.st_dev);
    append_opts(zopts, optsbuf);
  }
# endif /* MNTTAB_OPT_DEV */

  mnt->mnt_dir = old_mnt_dir;

# if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
  /*
   * add the extra vers={2,3} field to the mount table,
   * unless already specified by user
   */
   if (nfs_version == NFS_VERSION3 &&
       hasmntval(mnt, MNTTAB_OPT_VERS) != NFS_VERSION3) {
     sprintf(optsbuf, "%s=%d", MNTTAB_OPT_VERS, NFS_VERSION3);
     append_opts(zopts, optsbuf);
   }
# endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */

# ifdef MNTTAB_OPT_PROTO
  /*
   * add the extra proto={tcp,udp} field to the mount table,
   * unless already specified by user.
   */
  if (nfs_proto && !hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
    sprintf(optsbuf, "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
    append_opts(zopts, optsbuf);
  }
# endif /* MNTTAB_OPT_PROTO */

  /* finally, store the options into the mount table structure */
  mnt->mnt_opts = zopts;

  /*
   * Additional fields in mntent_t
   * are fixed up here
   */
# ifdef HAVE_MNTENT_T_MNT_CNODE
  mnt->mnt_cnode = 0;
# endif /* HAVE_MNTENT_T_MNT_CNODE */

# ifdef HAVE_MNTENT_T_MNT_RO
  mnt->mnt_ro = (hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
# endif /* HAVE_MNTENT_T_MNT_RO */

# ifdef HAVE_MNTENT_T_MNT_TIME
#  ifdef HAVE_MNTENT_T_MNT_TIME_STRING
  {				/* allocate enough space for a long */
    char *str = (char *) xmalloc(13 * sizeof(char));
    sprintf(str, "%ld", time((time_t *) NULL));
    mnt->mnt_time = str;
  }
#  else /* not HAVE_MNTENT_T_MNT_TIME_STRING */
  mnt->mnt_time = time((time_t *) NULL);
#  endif /* not HAVE_MNTENT_T_MNT_TIME_STRING */
# endif /* HAVE_MNTENT_T_MNT_TIME */

  write_mntent(mnt, mnttabname);

# ifdef MNTTAB_OPT_DEV
  if (xopts) {
    XFREE(mnt->mnt_opts);
    mnt->mnt_opts = xopts;
  }
# endif /* MNTTAB_OPT_DEV */
#endif /* MOUNT_TABLE_ON_FILE */

  return 0;
}
예제 #10
0
파일: autil.c 프로젝트: 0mp/freebsd
/*
 * Mount an automounter directory.
 * The automounter is connected into the system
 * as a user-level NFS server.  amfs_mount constructs
 * the necessary NFS parameters to be given to the
 * kernel so that it will talk back to us.
 *
 * NOTE: automounter mounts in themselves are using NFS Version 2 (UDP).
 *
 * NEW: on certain systems, mounting can be done using the
 * kernel-level automount (autofs) support. In that case,
 * we don't need NFS at all here.
 */
int
amfs_mount(am_node *mp, mntfs *mf, char *opts)
{
  char fs_hostname[MAXHOSTNAMELEN + MAXPATHLEN + 1];
  int retry, error = 0, genflags;
  int on_autofs = mf->mf_flags & MFF_ON_AUTOFS;
  char *dir = mf->mf_mount;
  mntent_t mnt;
  MTYPE_TYPE type;
  int forced_unmount = 0;	/* are we using forced unmounts? */
  u_long nfs_version = get_nfs_dispatcher_version(nfs_dispatcher);

  memset(&mnt, 0, sizeof(mnt));
  mnt.mnt_dir = dir;
  mnt.mnt_fsname = pid_fsname;
  mnt.mnt_opts = opts;

#ifdef HAVE_FS_AUTOFS
  if (mf->mf_flags & MFF_IS_AUTOFS) {
    type = MOUNT_TYPE_AUTOFS;
    /*
     * Make sure that amd's top-level autofs mounts are hidden by default
     * from df.
     * XXX: It works ok on Linux, might not work on other systems.
     */
    mnt.mnt_type = "autofs";
  } else
#endif /* HAVE_FS_AUTOFS */
  {
    type = MOUNT_TYPE_NFS;
    /*
     * Make sure that amd's top-level NFS mounts are hidden by default
     * from df.
     * If they don't appear to support the either the "ignore" mnttab
     * option entry, or the "auto" one, set the mount type to "nfs".
     */
    mnt.mnt_type = HIDE_MOUNT_TYPE;
  }

  retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
  if (retry <= 0)
    retry = 2;			/* XXX: default to 2 retries */

  /*
   * SET MOUNT ARGS
   */

  /*
   * Make a ``hostname'' string for the kernel
   */
  xsnprintf(fs_hostname, sizeof(fs_hostname), "pid%ld@%s:%s",
	    get_server_pid(), am_get_hostname(), dir);
  /*
   * Most kernels have a name length restriction (64 bytes)...
   */
  if (strlen(fs_hostname) >= MAXHOSTNAMELEN)
    xstrlcpy(fs_hostname + MAXHOSTNAMELEN - 3, "..",
	     sizeof(fs_hostname) - MAXHOSTNAMELEN + 3);
#ifdef HOSTNAMESZ
  /*
   * ... and some of these restrictions are 32 bytes (HOSTNAMESZ)
   * If you need to get the definition for HOSTNAMESZ found, you may
   * add the proper header file to the conf/nfs_prot/nfs_prot_*.h file.
   */
  if (strlen(fs_hostname) >= HOSTNAMESZ)
    xstrlcpy(fs_hostname + HOSTNAMESZ - 3, "..",
	     sizeof(fs_hostname) - HOSTNAMESZ + 3);
#endif /* HOSTNAMESZ */

  /*
   * Finally we can compute the mount genflags set above,
   * and add any automounter specific flags.
   */
  genflags = compute_mount_flags(&mnt);
#ifdef HAVE_FS_AUTOFS
  if (on_autofs)
    genflags |= autofs_compute_mount_flags(&mnt);
#endif /* HAVE_FS_AUTOFS */
  genflags |= compute_automounter_mount_flags(&mnt);

again:
  if (!(mf->mf_flags & MFF_IS_AUTOFS)) {
    nfs_args_t nfs_args;
    am_nfs_handle_t *fhp, anh;
#ifndef HAVE_TRANSPORT_TYPE_TLI
    u_short port;
    struct sockaddr_in sin;
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*
     * get fhandle of remote path for automount point
     */
    fhp = get_root_nfs_fh(dir, &anh);
    if (!fhp) {
      plog(XLOG_FATAL, "Can't find root file handle for %s", dir);
      return EINVAL;
    }

#ifndef HAVE_TRANSPORT_TYPE_TLI
    /*
     * Create sockaddr to point to the local machine.
     */
    memset(&sin, 0, sizeof(sin));
    /* as per POSIX, sin_len need not be set (used internally by kernel) */
    sin.sin_family = AF_INET;
    sin.sin_addr = myipaddr;
    port = hasmntval(&mnt, MNTTAB_OPT_PORT);
    if (port) {
      sin.sin_port = htons(port);
    } else {
      plog(XLOG_ERROR, "no port number specified for %s", dir);
      return EINVAL;
    }
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /* setup the many fields and flags within nfs_args */
#ifdef HAVE_TRANSPORT_TYPE_TLI
    compute_nfs_args(&nfs_args,
		     &mnt,
		     genflags,
		     nfsncp,
		     NULL,	/* remote host IP addr is set below */
		     nfs_version,
		     "udp",
		     fhp,
		     fs_hostname,
		     pid_fsname);
    /*
     * IMPORTANT: set the correct IP address AFTERWARDS.  It cannot
     * be done using the normal mechanism of compute_nfs_args(), because
     * that one will allocate a new address and use NFS_SA_DREF() to copy
     * parts to it, while assuming that the ip_addr passed is always
     * a "struct sockaddr_in".  That assumption is incorrect on TLI systems,
     * because they define a special macro HOST_SELF which is DIFFERENT
     * than localhost (127.0.0.1)!
     */
    nfs_args.addr = &nfsxprt->xp_ltaddr;
#else /* not HAVE_TRANSPORT_TYPE_TLI */
    compute_nfs_args(&nfs_args,
		     &mnt,
		     genflags,
		     NULL,
		     &sin,
		     nfs_version,
		     "udp",
		     fhp,
		     fs_hostname,
		     pid_fsname);
#endif /* not HAVE_TRANSPORT_TYPE_TLI */

    /*************************************************************************
     * NOTE: while compute_nfs_args() works ok for regular NFS mounts	     *
     * the toplvl one is not quite regular, and so some options must be      *
     * corrected by hand more carefully, *after* compute_nfs_args() runs.    *
     *************************************************************************/
    compute_automounter_nfs_args(&nfs_args, &mnt);

    if (amuDebug(D_TRACE)) {
      print_nfs_args(&nfs_args, 0);
      plog(XLOG_DEBUG, "Generic mount flags 0x%x", genflags);
    }

    /* This is it!  Here we try to mount amd on its mount points */
    error = mount_fs(&mnt, genflags, (caddr_t) &nfs_args,
		     retry, type, 0, NULL, mnttab_file_name, on_autofs);

#ifdef HAVE_TRANSPORT_TYPE_TLI
    free_knetconfig(nfs_args.knconf);
    /*
     * local automounter mounts do not allocate a special address, so
     * no need to XFREE(nfs_args.addr) under TLI.
     */
#endif /* HAVE_TRANSPORT_TYPE_TLI */

#ifdef HAVE_FS_AUTOFS
  } else {
    /* This is it!  Here we try to mount amd on its mount points */
    error = mount_fs(&mnt, genflags, (caddr_t) mp->am_autofs_fh,
		     retry, type, 0, NULL, mnttab_file_name, on_autofs);
#endif /* HAVE_FS_AUTOFS */
  }
  if (error == 0 || forced_unmount)
     return error;

  /*
   * If user wants forced/lazy unmount semantics, then try it iff the
   * current mount failed with EIO or ESTALE.
   */
  if (gopt.flags & CFM_FORCED_UNMOUNTS) {
    switch (errno) {
    case ESTALE:
    case EIO:
      forced_unmount = errno;
      plog(XLOG_WARNING, "Mount %s failed (%m); force unmount.", mp->am_path);
      if ((error = UMOUNT_FS(mp->am_path, mnttab_file_name,
			     AMU_UMOUNT_FORCE | AMU_UMOUNT_DETACH)) < 0) {
	plog(XLOG_WARNING, "Forced umount %s failed: %m.", mp->am_path);
	errno = forced_unmount;
      } else
	goto again;
    default:
      break;
    }
  }

  return error;
}
예제 #11
0
파일: autil.c 프로젝트: 0mp/freebsd
void
am_mounted(am_node *mp)
{
  int notimeout = 0;		/* assume normal timeouts initially */
  mntfs *mf = mp->am_al->al_mnt;

  /*
   * This is the parent mntfs which does the mf->mf_fo (am_opts type), and
   * we're passing TRUE here to tell mf_mounted to actually free the
   * am_opts.  See a related comment in mf_mounted().
   */
  mf_mounted(mf, TRUE);

#ifdef HAVE_FS_AUTOFS
  if (mf->mf_flags & MFF_IS_AUTOFS)
    autofs_mounted(mp);
#endif /* HAVE_FS_AUTOFS */

  /*
   * Patch up path for direct mounts
   */
  if (mp->am_parent && mp->am_parent->am_al->al_mnt->mf_fsflags & FS_DIRECT)
    mp->am_path = str3cat(mp->am_path, mp->am_parent->am_path, "/", ".");

  /*
   * Check whether this mount should be cached permanently or not,
   * and handle user-requested timeouts.
   */
  /* first check if file system was set to never timeout */
  if (mf->mf_fsflags & FS_NOTIMEOUT)
    notimeout = 1;
  /* next, alter that decision by map flags */

  if (mf->mf_mopts) {
    mntent_t mnt;
    mnt.mnt_opts = mf->mf_mopts;

    /* umount option: user wants to unmount this entry */
    if (amu_hasmntopt(&mnt, "unmount") || amu_hasmntopt(&mnt, "umount"))
      notimeout = 0;
    /* noumount option: user does NOT want to unmount this entry */
    if (amu_hasmntopt(&mnt, "nounmount") || amu_hasmntopt(&mnt, "noumount"))
      notimeout = 1;
    /* utimeout=N option: user wants to unmount this option AND set timeout */
    if ((mp->am_timeo = hasmntval(&mnt, "utimeout")) == 0)
      mp->am_timeo = gopt.am_timeo; /* otherwise use default timeout */
    else
      notimeout = 0;
    /* special case: don't try to unmount "/" (it can never succeed) */
    if (mf->mf_mount[0] == '/' && mf->mf_mount[1] == '\0')
      notimeout = 1;
  }
  /* finally set actual flags */
  if (notimeout) {
    mp->am_flags |= AMF_NOTIMEOUT;
    plog(XLOG_INFO, "%s set to never timeout", mp->am_path);
  } else {
    mp->am_flags &= ~AMF_NOTIMEOUT;
    plog(XLOG_INFO, "%s set to timeout in %d seconds", mp->am_path, mp->am_timeo);
  }

  /*
   * If this node is a symlink then
   * compute the length of the returned string.
   */
  if (mp->am_fattr.na_type == NFLNK)
    mp->am_fattr.na_size = strlen(mp->am_link ? mp->am_link : mf->mf_mount);

  /*
   * Record mount time, and update am_stats at the same time.
   */
  mp->am_stats.s_mtime = clocktime(&mp->am_fattr.na_mtime);
  new_ttl(mp);

  /*
   * Update mtime of parent node (copying "struct nfstime" in '=' below)
   */
  if (mp->am_parent && mp->am_parent->am_al->al_mnt)
    mp->am_parent->am_fattr.na_mtime = mp->am_fattr.na_mtime;

  /*
   * This is ugly, but essentially unavoidable
   * Sublinks must be treated separately as type==link
   * when the base type is different.
   */
  if (mp->am_link && mf->mf_ops != &amfs_link_ops)
    amfs_link_ops.mount_fs(mp, mf);

  /*
   * Now, if we can, do a reply to our client here
   * to speed things up.
   */
#ifdef HAVE_FS_AUTOFS
  if (mp->am_flags & AMF_AUTOFS)
    autofs_mount_succeeded(mp);
  else
#endif /* HAVE_FS_AUTOFS */
    nfs_quick_reply(mp, 0);

  /*
   * Update stats
   */
  amd_stats.d_mok++;
}