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); }
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; }
/* * 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); } }