示例#1
0
int SMBCheckForAlreadyMountedShare(SMBHANDLE inConnection,
                                   CFStringRef shareRef, CFMutableDictionaryRef mdictRef,
                                   struct statfs *fs, int fs_cnt)
{
    void * hContext;
    NTSTATUS status;
    CFMutableStringRef upperStringRef;
    char ShareName[SMB_MAXSHARENAMELEN + 1];

    memset(ShareName, 0, sizeof(ShareName));
    status = SMBServerContext(inConnection, &hContext);
    if (!NT_SUCCESS(status)) {
        return EBADF;
    }
    upperStringRef = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, shareRef);
    if (upperStringRef == NULL) {
        return ENOMEM;
    }
    CFStringUppercase(upperStringRef, NULL);
    CFStringGetCString(upperStringRef, ShareName, SMB_MAXSHARENAMELEN + 1, kCFStringEncodingUTF8);
    CFRelease(upperStringRef);
    return already_mounted(hContext, ShareName, fs, fs_cnt, mdictRef, 0);
}
示例#2
0
static int
amfs_host_mount(am_node *am, mntfs *mf)
{
  struct timeval tv2;
  CLIENT *client;
  enum clnt_stat clnt_stat;
  int n_export;
  int j, k;
  exports exlist = 0, ex;
  exports *ep = NULL;
  am_nfs_handle_t *fp = NULL;
  char *host;
  int error = 0;
  struct sockaddr_in sin;
  int sock = RPC_ANYSOCK;
  int ok = FALSE;
  mntlist *mlist;
  char fs_name[MAXPATHLEN], *rfs_dir;
  char mntpt[MAXPATHLEN];
  struct timeval tv;
  u_long mnt_version;

  /*
   * WebNFS servers don't necessarily run mountd.
   */
  if (mf->mf_flags & MFF_WEBNFS) {
    plog(XLOG_ERROR, "amfs_host_mount: cannot support WebNFS");
    return EIO;
  }

  /*
   * Read the mount list
   */
  mlist = read_mtab(mf->mf_mount, mnttab_file_name);

#ifdef MOUNT_TABLE_ON_FILE
  /*
   * Unlock the mount list
   */
  unlock_mntlist();
#endif /* MOUNT_TABLE_ON_FILE */

  /*
   * Take a copy of the server hostname, address, and nfs version
   * to mount version conversion.
   */
  host = mf->mf_server->fs_host;
  sin = *mf->mf_server->fs_ip;
  plog(XLOG_INFO, "amfs_host_mount: NFS version %d", (int) mf->mf_server->fs_version);
#ifdef HAVE_FS_NFS3
  if (mf->mf_server->fs_version == NFS_VERSION3)
    mnt_version = AM_MOUNTVERS3;
  else
#endif /* HAVE_FS_NFS3 */
    mnt_version = MOUNTVERS;

  /*
   * The original 10 second per try timeout is WAY too large, especially
   * if we're only waiting 10 or 20 seconds max for the response.
   * That would mean we'd try only once in 10 seconds, and we could
   * lose the transmit or receive packet, and never try again.
   * A 2-second per try timeout here is much more reasonable.
   * 09/28/92 Mike Mitchell, [email protected]
   */
  tv.tv_sec = 2;
  tv.tv_usec = 0;

  /*
   * Create a client attached to mountd
   */
  client = get_mount_client(host, &sin, &tv, &sock, mnt_version);
  if (client == NULL) {
#ifdef HAVE_CLNT_SPCREATEERROR
    plog(XLOG_ERROR, "get_mount_client failed for %s: %s",
	 host, clnt_spcreateerror(""));
#else /* not HAVE_CLNT_SPCREATEERROR */
    plog(XLOG_ERROR, "get_mount_client failed for %s", host);
#endif /* not HAVE_CLNT_SPCREATEERROR */
    error = EIO;
    goto out;
  }
  if (!nfs_auth) {
    error = make_nfs_auth();
    if (error)
      goto out;
  }
  client->cl_auth = nfs_auth;

  dlog("Fetching export list from %s", host);

  /*
   * Fetch the export list
   */
  tv2.tv_sec = 10;
  tv2.tv_usec = 0;
  clnt_stat = clnt_call(client,
			MOUNTPROC_EXPORT,
			(XDRPROC_T_TYPE) xdr_void,
			0,
			(XDRPROC_T_TYPE) xdr_exports,
			(SVC_IN_ARG_TYPE) & exlist,
			tv2);
  if (clnt_stat != RPC_SUCCESS) {
    const char *msg = clnt_sperrno(clnt_stat);
    plog(XLOG_ERROR, "host_mount rpc failed: %s", msg);
    /* clnt_perror(client, "rpc"); */
    error = EIO;
    goto out;
  }

  /*
   * Figure out how many exports were returned
   */
  for (n_export = 0, ex = exlist; ex; ex = ex->ex_next) {
    n_export++;
  }

  /*
   * Allocate an array of pointers into the list
   * so that they can be sorted.  If the filesystem
   * is already mounted then ignore it.
   */
  ep = (exports *) xmalloc(n_export * sizeof(exports));
  for (j = 0, ex = exlist; ex; ex = ex->ex_next) {
    make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount);
    if (already_mounted(mlist, mntpt))
      /* we have at least one mounted f/s, so don't fail the mount */
      ok = TRUE;
    else
      ep[j++] = ex;
  }
  n_export = j;

  /*
   * Sort into order.
   * This way the mounts are done in order down the tree,
   * instead of any random order returned by the mount
   * daemon (the protocol doesn't specify...).
   */
  qsort(ep, n_export, sizeof(exports), sortfun);

  /*
   * Allocate an array of filehandles
   */
  fp = (am_nfs_handle_t *) xmalloc(n_export * sizeof(am_nfs_handle_t));

  /*
   * Try to obtain filehandles for each directory.
   * If a fetch fails then just zero out the array
   * reference but discard the error.
   */
  for (j = k = 0; j < n_export; j++) {
    /* Check and avoid a duplicated export entry */
    if (j > k && ep[k] && STREQ(ep[j]->ex_dir, ep[k]->ex_dir)) {
      dlog("avoiding dup fhandle requested for %s", ep[j]->ex_dir);
      ep[j] = NULL;
    } else {
      k = j;
      error = fetch_fhandle(client, ep[j]->ex_dir, &fp[j],
			    mf->mf_server->fs_version);
      if (error)
	ep[j] = NULL;
    }
  }

  /*
   * Mount each filesystem for which we have a filehandle.
   * If any of the mounts succeed then mark "ok" and return
   * error code 0 at the end.  If they all fail then return
   * the last error code.
   */
  xstrlcpy(fs_name, mf->mf_info, sizeof(fs_name));
  if ((rfs_dir = strchr(fs_name, ':')) == (char *) NULL) {
    plog(XLOG_FATAL, "amfs_host_mount: mf_info has no colon");
    error = EINVAL;
    goto out;
  }
  ++rfs_dir;
  for (j = 0; j < n_export; j++) {
    ex = ep[j];
    if (ex) {
      /*
       * Note: the sizeof space left in rfs_dir is what's left in fs_name
       * after strchr() above returned a pointer _inside_ fs_name.  The
       * calculation below also takes into account that rfs_dir was
       * incremented by the ++ above.
       */
      xstrlcpy(rfs_dir, ex->ex_dir, sizeof(fs_name) - (rfs_dir - fs_name));
      make_mntpt(mntpt, sizeof(mntpt), ex, mf->mf_mount);
      if (do_mount(&fp[j], mntpt, fs_name, mf) == 0)
	ok = TRUE;
    }
  }

  /*
   * Clean up and exit
   */
out:
  discard_mntlist(mlist);
  XFREE(ep);
  XFREE(fp);
  if (sock != RPC_ANYSOCK)
    (void) amu_close(sock);
  if (client)
    clnt_destroy(client);
  if (exlist)
    xdr_pri_free((XDRPROC_T_TYPE) xdr_exports, (caddr_t) &exlist);
  if (ok)
    return 0;
  return error;
}
示例#3
0
/*
 * get_mntinfo - get the mount table, now dynamically allocated. Returns 0 if
 * no problem and 1 if there's a fatal error.
 */
int
get_mntinfo(int map_client, char *vfstab_file)
{
	static 	char 	*rn = "/";
	FILE		*pp;
	struct	mnttab	mtbuf;
	struct	mnttab	*mt = &mtbuf;
	char		*install_root;
	int 		is_remote;

	/*
	 * Open the mount table for the current host and establish a global
	 * table that holds data about current mount status.
	 */
	if ((pp = setmntent(MOUNT_TABLE, "r")) == NULL) {
		progerr(ERR_NOTABLE, "mount", MOUNT_TABLE, strerror(errno));
		return (1);
	}

	/*
	 * First, review the mounted filesystems on the managing host. This
	 * may also be the target host but we haven't decided that for sure
	 * yet.
	 */
	while (!getmntent(pp, mt))
		if (construct_mt(mt))
			return (1);

	(void) endmntent(pp);

	/*
	 * Now, we see if this installation is to a client. If it is, we scan
	 * the client's vfstab to determine what filesystems are
	 * inappropriate to write to. This simply adds the vfstab entries
	 * representing what will be remote file systems for the client.
	 * Everything that isn't remote to the client is already accounted
	 * for in the fs_tab[] so far. If the remote filesystem is really on
	 * this server, we will write through to the server from this client.
	 */
	install_root = get_inst_root();
	if (install_root && strcmp(install_root, "/") != 0 && map_client) {
		/* OK, this is a legitimate remote client. */
		struct	vfstab	vfsbuf;
		struct	vfstab	*vfs = &vfsbuf;
		char VFS_TABLE[PATH_MAX];

		/*
		 * Since we use the fsys() function later, and it depends on
		 * an ordered list, we have to sort the list here.
		 */
		qsort(fs_tab, fs_tab_used,
		    sizeof (struct fstable *), fs_tab_ent_comp);

		/*
		 * Here's where the vfstab for the target is. If we can get
		 * to it, we'll scan it for what the client will see as
		 * remote filesystems, otherwise, we'll just skip this.
		 */
		if (vfstab_file) {
			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s",
			    vfstab_file);
		} else {
			(void) snprintf(VFS_TABLE, sizeof (VFS_TABLE), "%s%s",
			    install_root, VFSTAB);
		}

		if (access(VFS_TABLE, R_OK) == 0) {
			char *link_name;

			/*
			 * Open the vfs table for the target host.
			 */
			if ((pp = setmntent(VFS_TABLE, "r")) == NULL) {
				progerr(ERR_NOTABLE, "vfs", VFS_TABLE,
				    strerror(errno));
				return (1);
			}

			/* Do this for each entry in the vfstab. */
			while (!getvfsent(pp, vfs)) {
				char client_mountp[PATH_MAX];
				int mnt_stat;

				/*
				 * We put it into the fs table if it's
				 * remote mounted (even from this server) or
				 * loopback mounted from the client's point
				 * of view.
				 */
				if (!(is_remote =
				    is_remote_src(vfs->vfs_special)) &&
				    strcmp(vfs->vfs_fstype, MNTTYPE_LOFS) !=
				    0)
					continue;	/* not interesting */

				/*
				 * Construct client_mountp by prepending the
				 * install_root to the 'mount point' name.
				 */
				if (strcmp(vfs->vfs_mountp, "/") == 0) {
					(void) strcpy(client_mountp,
					    install_root);
				} else {
					(void) snprintf(client_mountp,
					    sizeof (client_mountp), "%s%s",
					    install_root, vfs->vfs_mountp);
				}

				/*
				 * We also skip the entry if the vfs_special
				 * path and the client_path are the same.
				 * There's no need to mount it, it's just a
				 * cachefs optimization that mounts a
				 * directory over itself from this server.
				 */
				if ((is_remote == SELF_SERVE) &&
				    strcmp(path_part(vfs->vfs_special),
				    client_mountp) == 0)
					continue;

				/* Determine if this is already mounted. */
				link_name = strdup(path_part(vfs->vfs_special));
				mnt_stat = already_mounted(vfs,
				    (is_remote != REAL_REMOTE), client_mountp,
				    link_name);

				if (mnt_stat == MNT_EXACT) {
					mod_existing(vfs, match_mount,
					    is_remote);
				} else {	/* MNT_NOT */
					if (construct_vfs(vfs, client_mountp,
					    link_name, is_remote, mnt_stat)) {
						return (1);
					}
				}
			}
			(void) endmntent(pp);
		}	/* end of if(access()) */
	}	/* end of if(install_root) */

	/* This next one may look stupid, but it can really happen. */
	if (fs_tab_used <= 0) {
		progerr(ERR_MNT_NOMOUNTS);
		return (1);
	}

	/*
	 * Now that we have the complete list of mounted (or virtually
	 * mounted) filesystems, we sort the mountpoints in reverse order
	 * based on the length of the 'mount point' name.
	 */
	qsort(fs_tab, fs_tab_used, sizeof (struct fstable *), fs_tab_ent_comp);
	if (strcmp(fs_tab[fs_tab_used-1]->name, rn) != 0) {
		progerr(ERR_MNT_NOROOT, fs_tab[fs_tab_used-1]->name, rn, errno,
		    strerror(errno));
		return (1);
	} else {
		return (0);
	}
}