static mntent_t * mnt_dup(struct vmount *mp) { mntent_t *new_mp = ALLOC(mntent_t); char *ty; char *fsname = strdup(vmt2dataptr(mp, VMT_OBJECT)); new_mp->mnt_dir = strdup(vmt2dataptr(mp, VMT_STUB)); new_mp->mnt_opts = strdup(vmt2dataptr(mp, VMT_ARGS)); switch (mp->vmt_gfstype) { case MOUNT_TYPE_UFS: ty = MNTTAB_TYPE_UFS; new_mp->mnt_fsname = strdup(fsname); break; case MOUNT_TYPE_NFS: ty = MNTTAB_TYPE_NFS; new_mp->mnt_fsname = str3cat((char *) 0, vmt2dataptr(mp, VMT_HOSTNAME), ":", fsname); break; #ifdef HAVE_FS_NFS3 case MOUNT_TYPE_NFS3: ty = MNTTAB_TYPE_NFS3; new_mp->mnt_fsname = str3cat((char *) 0, vmt2dataptr(mp, VMT_HOSTNAME), ":", fsname); break; #endif /* HAVE_FS_NFS3 */ default: ty = "unknown"; new_mp->mnt_fsname = strdup(fsname); break; } new_mp->mnt_type = strdup(ty); /* store the VFS ID for uvmount() */ new_mp->mnt_passno = mp->vmt_vfsnumber; new_mp->mnt_freq = 0; XFREE(fsname); return new_mp; }
/* * SFS needs a link. */ char * amfs_link_match(am_opts *fo) { if (!fo->opt_fs) { plog(XLOG_USER, "link: no fs specified"); return 0; } /* * If the link target points to another mount point, then we could * end up with an unpleasant situation, where the link f/s simply * "assumes" the mntfs of that mount point. * * For example, if the link points to /usr, and /usr is a real ufs * filesystem, then the link f/s will use the inherited ufs mntfs, * and the end result will be that it will become unmountable. * * To prevent this, we use a hack: we prepend a dot ('.') to opt_fs if * its original value was an absolute path, so that it will never match * any other mntfs. * * XXX: a less hacky solution should be used... */ if (fo->opt_fs[0] == '/') { char *link_hack = str3cat(NULL, ".", fo->opt_fs, ""); if (fo->opt_sublink == NULL || fo->opt_sublink[0] == '\0') fo->opt_sublink = strdup(fo->opt_fs); XFREE(fo->opt_fs); fo->opt_fs = link_hack; } return strdup(fo->opt_fs); }
/* * SFS needs a link. */ char * amfs_link_match(am_opts *fo) { if (!fo->opt_fs) { plog(XLOG_USER, "link: no fs specified"); return 0; } /* * Bug report (14/12/89) from Jay Plett <*****@*****.**> * If an automount point has the same name as an existing * link type mount Amd hits a race condition and either hangs * or causes a symlink loop. * * If fs begins with a '/' change the opt_fs & opt_sublink * fields so that the fs option doesn't end up pointing at * an existing symlink. * * If sublink is nil then set sublink to fs * else set sublink to fs / sublink * * Finally set fs to ".". */ if (*fo->opt_fs == '/') { char *fullpath; char *link = fo->opt_sublink; if (link) { if (*link == '/') fullpath = strdup(link); else fullpath = str3cat((char *) 0, fo->opt_fs, "/", link); } else { fullpath = strdup(fo->opt_fs); } if (fo->opt_sublink) XFREE(fo->opt_sublink); fo->opt_sublink = fullpath; fo->opt_fs = str3cat(fo->opt_fs, ".", fullpath, ""); } return strdup(fo->opt_fs); }
static char * amfs_nfsx_match(am_opts *fo) { char *xmtab; char *ptr; int len; if (!fo->opt_rfs) { plog(XLOG_USER, "amfs_nfsx: no remote filesystem specified"); return FALSE; } if (!fo->opt_rhost) { plog(XLOG_USER, "amfs_nfsx: no remote host specified"); return FALSE; } /* set default sublink */ if (fo->opt_sublink == 0) { ptr = strchr(fo->opt_rfs, ','); if (ptr && ptr > (fo->opt_rfs + 1)) fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1); } /* * Remove trailing ",..." from ${fs} * After deslashifying, overwrite the end of ${fs} with "/" * to make sure it is unique. */ if ((ptr = strchr(fo->opt_fs, ','))) *ptr = '\0'; deslashify(fo->opt_fs); /* * Bump string length to allow trailing / */ len = strlen(fo->opt_fs); fo->opt_fs = xrealloc(fo->opt_fs, len + 1 + 1); ptr = fo->opt_fs + len; /* * Make unique... */ *ptr++ = '/'; *ptr = '\0'; /* * Determine magic cookie to put in mtab */ xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs); dlog("NFSX: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"", fo->opt_rhost, fo->opt_rfs, fo->opt_fs); return xmtab; }
char *replace(char *text, char *from, char *to){ //if (DEBUG==1) putlog("replacing"); char *ret=(char*)calloc( strlen(text)+(strlen(to)-strlen(from)),sizeof(char)); char *left; char *right; int pos=inStr(text,strlen(text),from); if (pos!=-1){ left=substring(text,0,pos); right=substring(text,pos+strlen(from),strlen(text)-(pos+strlen(from))); ret=str3cat(left,to,right); return replace(ret,from,to); } //if (DEBUG==1) putlog("replaced"); return text; }
void loadThemes() { char *hDir, *hFile, *line, *lineCap, *val; FILE *f; hexchat_print(ph,"loading themes\n"); hDir=(char*)calloc(1024,sizeof(char)); strcpy(hDir,hexchat_get_info(ph,"configdir")); hFile=str3cat(hDir,"\\","mpcInfo.theme.txt"); f = fopen(hFile,"r"); free(hDir); free(hFile); if(f==NULL) { hexchat_print(ph,"no theme in homedir, checking global theme"); f=fopen("mpcInfo.theme.txt","r"); } //hexchat_printf(ph,"file_desc: %p\n",f); if (f==NULL) hexchat_print(ph, "no theme found, using hardcoded\n"); else { if (f > 0) { line=" "; } else { line="\0"; } while (line[0]!=0) { line=readLine(f); val=split(line,'='); printf("line: %s\n",line); printf("val: %s\n",val); lineCap=toUpper(line); if (strcmp(lineCap,"OFF_LINE")==0) notRunTheme=themeAdd(notRunTheme,val); if (strcmp(lineCap,"TITLE_LINE")==0) titleTheme=themeAdd(titleTheme,val); if (strcmp(lineCap,"MP3_LINE")==0) mp3Theme=themeAdd(mp3Theme,val); if (strcmp(lineCap,"OGG_LINE")==0) mp3Theme=themeAdd(oggTheme,val); free(lineCap); } fclose(f); hexchat_print(ph, "theme loaded successfull\n"); } if (notRunTheme.size==0) notRunTheme=themeAdd(notRunTheme,"Media Player Classic not running"); if (titleTheme.size==0) titleTheme=themeAdd(titleTheme,"say Playing %title in Media Player Classic"); if (mp3Theme.size==0) mp3Theme=themeAdd(mp3Theme,"me listens to %art with %tit from %alb [%gen|%br kbps|%frq kHz|%mode] in Media Player Classic "); if (oggTheme.size==0) oggTheme=themeAdd(oggTheme,"me listens to %art with %tit from %alb [%gen|%br kbps|%frq kHz|%chan channels] in Media Player Classic "); //mp3Theme=themeAdd(mp3Theme,"me listens to %art with %tit from %alb [%time|%length|%perc%|%br kbps|%frq kHz|%mode] in Media Player Classic "); }
static void autofs_expire_one(am_node *mp, char *name, unsigned long token) { autofs_fh_t *fh; am_node *ap; struct autofs_pending_umount *p; char *ap_path; fh = mp->am_autofs_fh; ap_path = str3cat(NULL, mp->am_path, "/", name); if (amuDebug(D_TRACE)) plog(XLOG_DEBUG, "\tumount(%s)", ap_path); p = fh->pending_umounts; while (p && p->wait_queue_token != token) p = p->next; if (p) { /* already pending */ dlog("Umounting of %s already pending", ap_path); amd_stats.d_drops++; goto out; } ap = find_ap(ap_path); if (ap == NULL) { /* not found??? not sure what to do here... */ send_fail(fh->ioctlfd, token); goto out; } p = ALLOC(struct autofs_pending_umount); p->wait_queue_token = token; p->name = strdup(name); p->next = fh->pending_umounts; fh->pending_umounts = p; unmount_mp(ap); out: XFREE(ap_path); }
/* * Execute needs a mount and unmount command. */ static char * amfs_program_match(am_opts *fo) { char *prog; if (fo->opt_unmount && fo->opt_umount) { plog(XLOG_ERROR, "program: cannot specify both unmount and umount options"); return 0; } if (!fo->opt_mount) { plog(XLOG_ERROR, "program: must specify mount command"); return 0; } if (!fo->opt_unmount && !fo->opt_umount) { fo->opt_unmount = str3cat(NULL, UNMOUNT_PROGRAM, " umount ", fo->opt_fs); plog(XLOG_INFO, "program: un/umount not specified; using default \"%s\"", fo->opt_unmount); } prog = strchr(fo->opt_mount, ' '); return strdup(prog ? prog + 1 : fo->opt_mount); }
am_node * get_ap_child(am_node *mp, char *fname) { am_node *new_mp; mntfs *mf = mp->am_mnt; /* * Allocate a new map */ new_mp = exported_ap_alloc(); if (new_mp) { /* * Fill it in */ init_map(new_mp, fname); /* * Put it in the table */ insert_am(new_mp, mp); /* * Fill in some other fields, * path and mount point. * * bugfix: do not prepend old am_path if direct map * <*****@*****.**> William Sebok */ new_mp->am_path = str3cat(new_mp->am_path, (mf->mf_fsflags & FS_DIRECT) ? "" : mp->am_path, *fname == '/' ? "" : "/", fname); dlog("setting path to %s", new_mp->am_path); } return new_mp; }
static int amfs_nfsx_init(mntfs *mf) { /* * mf_info has the form: * host:/prefix/path,sub,sub,sub */ int i; int glob_error; struct amfs_nfsx *nx; int asked_for_wakeup = 0; nx = (struct amfs_nfsx *) mf->mf_private; if (nx == 0) { char **ivec; char *info = 0; char *host; char *pref; int error = 0; info = strdup(mf->mf_info); host = strchr(info, ':'); if (!host) { error = EINVAL; goto errexit; } pref = host + 1; host = info; /* * Split the prefix off from the suffices */ ivec = strsplit(pref, ',', '\''); /* * Count array size */ for (i = 0; ivec[i]; i++) /* nothing */; nx = ALLOC(struct amfs_nfsx); mf->mf_private = (opaque_t) nx; mf->mf_prfree = amfs_nfsx_prfree; nx->nx_c = i - 1; /* i-1 because we don't want the prefix */ nx->nx_v = (amfs_nfsx_mnt *) xmalloc(nx->nx_c * sizeof(amfs_nfsx_mnt)); nx->nx_mp = 0; { char *mp = 0; char *xinfo = 0; char *fs = mf->mf_fo->opt_fs; char *rfs = 0; for (i = 0; i < nx->nx_c; i++) { char *path = ivec[i + 1]; rfs = str3cat(rfs, pref, "/", path); /* * Determine the mount point. * If this is the root, then don't remove * the trailing slash to avoid mntfs name clashes. */ mp = str3cat(mp, fs, "/", rfs); normalize_slash(mp); deslashify(mp); /* * Determine the mount info */ xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path); normalize_slash(xinfo); if (pref[1] != '\0') deslashify(xinfo); dlog("amfs_nfsx: init mount for %s on %s", xinfo, mp); nx->nx_v[i].n_error = -1; nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts); /* propagate the on_autofs flag */ nx->nx_v[i].n_mnt->mf_flags |= mf->mf_flags & MFF_ON_AUTOFS; } if (rfs) XFREE(rfs); if (mp) XFREE(mp); if (xinfo) XFREE(xinfo); } XFREE(ivec); errexit: if (info) XFREE(info); if (error) return error; }
static int nfsx_init(mntfs *mf) { /* * mf_info has the form: * host:/prefix/path,sub,sub,sub */ int i; int glob_error; struct nfsx *nx; int asked_for_wakeup = 0; nx = (struct nfsx *) mf->mf_private; if (nx == 0) { char **ivec; char *info = 0; char *host; char *pref; int error = 0; info = strdup(mf->mf_info); host = strchr(info, ':'); if (!host) { error = EINVAL; goto errexit; } pref = host+1; host = info; /* * Split the prefix off from the suffices */ ivec = strsplit(pref, ',', '\''); /* * Count array size */ for (i = 0; ivec[i]; i++) ; nx = ALLOC(nfsx); mf->mf_private = nx; mf->mf_prfree = nfsx_prfree; nx->nx_c = i - 1; /* i-1 because we don't want the prefix */ nx->nx_v = xreallocarray(NULL, nx->nx_c, sizeof *nx->nx_v); { char *mp = 0; char *xinfo = 0; char *fs = mf->mf_fo->opt_fs; char *rfs = 0; for (i = 0; i < nx->nx_c; i++) { char *path = ivec[i+1]; rfs = str3cat(rfs, pref, "/", path); /* * Determine the mount point. * If this is the root, then don't remove * the trailing slash to avoid mntfs name clashes. */ mp = str3cat(mp, fs, "/", rfs); normalize_slash(mp); deslashify(mp); /* * Determine the mount info */ xinfo = str3cat(xinfo, host, *path == '/' ? "" : "/", path); normalize_slash(xinfo); if (pref[1] != '\0') deslashify(xinfo); #ifdef DEBUG dlog("nfsx: init mount for %s on %s", xinfo, mp); #endif nx->nx_v[i].n_error = -1; nx->nx_v[i].n_mnt = find_mntfs(&nfs_ops, mf->mf_fo, mp, xinfo, "", mf->mf_mopts, mf->mf_remopts); } free(rfs); free(mp); free(xinfo); } free(ivec); errexit: free(info); if (error) return error; } /* * Iterate through the mntfs's and call * the underlying init routine on each */ glob_error = 0; for (i = 0; i < nx->nx_c; i++) { nfsx_mnt *n = &nx->nx_v[i]; mntfs *m = n->n_mnt; int error = (*m->mf_ops->fs_init)(m); /* * If HARD_NFSX_ERRORS is defined, make any * initialisation failure a hard error and * fail the entire group. Otherwise only fail * if none of the group is mountable (see nfsx_fmount). */ #ifdef HARD_NFSX_ERRORS if (error > 0) return error; #else if (error > 0) n->n_error = error; #endif else if (error < 0) { glob_error = -1; if (!asked_for_wakeup) { asked_for_wakeup = 1; sched_task(wakeup_task, mf, m); } } } return glob_error; }
am_ops * ops_match(am_opts *fo, char *key, char *g_key, char *path, char *keym, char *map) { am_ops *rop = NULL; char *link_dir; /* * First crack the global opts and the local opts */ if (!eval_fs_opts(fo, key, g_key, path, keym, map)) { rop = &amfs_error_ops; } else if (fo->opt_type == 0) { plog(XLOG_USER, "No fs type specified (key = \"%s\", map = \"%s\")", keym, map); rop = &amfs_error_ops; } else { /* * Next find the correct filesystem type */ rop = ops_search(fo->opt_type); if (!rop) { plog(XLOG_USER, "fs type \"%s\" not recognized", fo->opt_type); rop = &amfs_error_ops; } } /* * Make sure we have a default mount option. * Otherwise skip past any leading '-'. */ if (fo->opt_opts == 0) fo->opt_opts = strdup("rw,defaults"); else if (*fo->opt_opts == '-') { /* * We cannot simply do fo->opt_opts++ here since the opts * module will try to free the pointer fo->opt_opts later. * So just reallocate the thing -- stolcke 11/11/94 */ char *old = fo->opt_opts; fo->opt_opts = strdup(old + 1); XFREE(old); } /* * If addopts option was used, then append it to the * current options and remote mount options. */ if (fo->opt_addopts) { if (STREQ(fo->opt_opts, fo->opt_remopts)) { /* optimize things for the common case where opts==remopts */ char *mergedstr; mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts); plog(XLOG_INFO, "merge rem/opts \"%s\" add \"%s\" => \"%s\"", fo->opt_opts, fo->opt_addopts, mergedstr); XFREE(fo->opt_opts); XFREE(fo->opt_remopts); fo->opt_opts = mergedstr; fo->opt_remopts = strdup(mergedstr); } else { char *mergedstr, *remmergedstr; mergedstr = merge_opts(fo->opt_opts, fo->opt_addopts); plog(XLOG_INFO, "merge opts \"%s\" add \"%s\" => \"%s\"", fo->opt_opts, fo->opt_addopts, mergedstr); XFREE(fo->opt_opts); fo->opt_opts = mergedstr; remmergedstr = merge_opts(fo->opt_remopts, fo->opt_addopts); plog(XLOG_INFO, "merge remopts \"%s\" add \"%s\" => \"%s\"", fo->opt_remopts, fo->opt_addopts, remmergedstr); XFREE(fo->opt_remopts); fo->opt_remopts = remmergedstr; } } /* * Initialize opt_mount_type to "nfs", if it's not initialized already */ if (!fo->opt_mount_type) fo->opt_mount_type = "nfs"; /* Normalize the sublink and make it absolute */ link_dir = fo->opt_sublink; if (link_dir && link_dir[0] && link_dir[0] != '/') { link_dir = str3cat((char *) NULL, fo->opt_fs, "/", link_dir); normalize_slash(link_dir); XFREE(fo->opt_sublink); fo->opt_sublink = link_dir; } /* * Check the filesystem is happy */ if (fo->fs_mtab) XFREE(fo->fs_mtab); fo->fs_mtab = rop->fs_match(fo); if (fo->fs_mtab) return rop; /* * Return error file system */ fo->fs_mtab = amfs_error_ops.fs_match(fo); return &amfs_error_ops; }
int autofs_mount_fs(am_node *mp, mntfs *mf) { int err = 0; char *target, *target2 = NULL; char *space_hack = autofs_strdup_space_hack(mp->am_path); struct stat buf; if (mf->mf_flags & MFF_ON_AUTOFS) { if ((err = mkdir(space_hack, 0555))) goto out; } /* * For sublinks, we could end up here with an already mounted f/s. * Don't do anything in that case. */ if (!(mf->mf_flags & MFF_MOUNTED)) err = mf->mf_ops->mount_fs(mp, mf); if (err) { if (mf->mf_flags & MFF_ON_AUTOFS) rmdir(space_hack); errno = err; goto out; } /* * Autofs v1 doesn't support symlinks, * so we ignore the CFM_AUTOFS_USE_LOFS flag */ if (mf->mf_flags & MFF_ON_AUTOFS) /* Nothing to do */ goto out; if (mp->am_link) target = mp->am_link; else target = mf->mf_mount; if (target[0] != '/') target2 = str3cat(NULL, mp->am_parent->am_path, "/", target); else target2 = xstrdup(target); plog(XLOG_INFO, "autofs: converting from link to lofs (%s -> %s)", mp->am_path, target2); /* * we need to stat() the destination, because the bind mount does not * follow symlinks and/or allow for non-existent destinations. * * WARNING: we will deadlock if this function is called from the master * amd process and it happens to trigger another auto mount. Therefore, * this function should be called only from a child amd process, or * at the very least it should not be called from the parent unless we * know for sure that it won't cause a recursive mount. We refuse to * cause the recursive mount anyway if called from the parent amd. */ if (!foreground) { if ((err = stat(target2, &buf))) goto out; } if ((err = lstat(target2, &buf))) goto out; if ((err = mkdir(space_hack, 0555))) goto out; if ((err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1))) { errno = err; goto out; } out: XFREE(space_hack); if (target2) XFREE(target2); if (err) return errno; return 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++; }
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++; }
static void restart_fake_mntfs(mntent_t *me, am_ops *fs_ops) { mntfs *mf; am_opts mo; char *cp; /* * Partially fake up an opts structure */ memset(&mo, 0, sizeof(mo)); mo.opt_rhost = NULL; mo.opt_rfs = NULL; cp = strchr(me->mnt_fsname, ':'); if (cp) { *cp = '\0'; mo.opt_rhost = xstrdup(me->mnt_fsname); mo.opt_rfs = xstrdup(cp + 1); *cp = ':'; } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { /* * Hacky workaround for mnttab NFS entries that only list the server */ plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname); mo.opt_rhost = xstrdup(me->mnt_fsname); mo.opt_rfs = xstrdup("/"); me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/"); } mo.opt_fs = me->mnt_dir; mo.opt_opts = me->mnt_opts; /* * Make a new mounted filesystem */ mf = find_mntfs(fs_ops, &mo, me->mnt_dir, me->mnt_fsname, "", me->mnt_opts, ""); if (mf->mf_refc == 1) { mf->mf_flags |= MFF_RESTART | MFF_MOUNTED; mf->mf_error = 0; /* Already mounted correctly */ /* * Only timeout non-NFS entries */ if (!STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) mf->mf_flags |= MFF_RSTKEEP; if (fs_ops->fs_init) { /* * Don't care whether this worked since * it is checked again when the fs is * inherited. */ (void) (*fs_ops->fs_init) (mf); } plog(XLOG_INFO, "%s restarted fstype %s on %s, flags 0x%x", me->mnt_fsname, fs_ops->fs_type, me->mnt_dir, mf->mf_flags); } else { /* Something strange happened - two mounts at the same place! */ free_mntfs(mf); } /* * Clean up mo */ XFREE(mo.opt_rhost); XFREE(mo.opt_rfs); }
static char * nfsx_match(am_opts *fo) { char *xmtab; char *ptr; int len; if (!fo->opt_rfs) { plog(XLOG_USER, "nfsx: no remote filesystem specified"); return FALSE; } if (!fo->opt_rhost) { plog(XLOG_USER, "nfsx: no remote host specified"); return FALSE; } #ifdef notdef /* fiddle sublink, must be last... */ if (fo->opt_sublink) { plog(XLOG_WARNING, "nfsx: sublink %s ignored", fo->opt_sublink); free(fo->opt_sublink); fo->opt_sublink = 0; } #endif /* set default sublink */ if (fo->opt_sublink == 0) { ptr = strchr(fo->opt_rfs, ','); if (ptr && ptr != (fo->opt_rfs + 1)) fo->opt_sublink = strnsave(fo->opt_rfs + 1, ptr - fo->opt_rfs - 1); } /* * Remove trailing ",..." from ${fs} * After deslashifying, overwrite the end of ${fs} with "/" * to make sure it is unique. */ if ((ptr = strchr(fo->opt_fs, ','))) *ptr = '\0'; deslashify(fo->opt_fs); /* * Bump string length to allow trailing / */ len = strlen(fo->opt_fs); if (len > SIZE_MAX - 2) xmallocfailure(); fo->opt_fs = xreallocarray(fo->opt_fs, len + 1 + 1, 1); ptr = fo->opt_fs + len; /* * Make unique... */ *ptr++ = '/'; *ptr = '\0'; /* * Determine magic cookie to put in mtab */ xmtab = str3cat((char *) 0, fo->opt_rhost, ":", fo->opt_rfs); #ifdef DEBUG dlog("NFS: mounting remote server \"%s\", remote fs \"%s\" on \"%s\"", fo->opt_rhost, fo->opt_rfs, fo->opt_fs); #endif /* DEBUG */ return xmtab; }
/* * Handle an amd restart. * * Scan through the mount list finding all "interesting" mount points. * Next hack up partial data structures and add the mounted file * system to the list of known filesystems. This will leave a * dangling reference to that filesystems, so when the filesystem is * finally inherited, an extra "free" must be done on it. * * This module relies on internal details of other components. If * you change something else make *sure* restart() still works. */ void restart(void) { /* * Read the existing mount table */ mntlist *ml, *mlp; /* * For each entry, find nfs, ufs or auto mounts * and create a partial am_node to represent it. */ for (mlp = ml = read_mtab("restart", mnttab_file_name); mlp; mlp = mlp->mnext) { mntent_t *me = mlp->mnt; am_ops *fs_ops = 0; if (STREQ(me->mnt_type, MNTTAB_TYPE_UFS)) { /* * UFS entry */ fs_ops = &ufs_ops; } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS)) { /* * NFS entry, or possibly an Amd entry... * The mnt_fsname for daemon mount points is * host:(pidXXX) * or (seen on Solaris) * host:daemon(pidXXX) */ char *colon = strchr(me->mnt_fsname, ':'); if (colon && strstr(colon, "(pid")) { plog(XLOG_WARNING, "%s is an existing automount point", me->mnt_dir); fs_ops = &amfs_link_ops; } else { fs_ops = &nfs_ops; } #ifdef MNTTAB_TYPE_NFS3 } else if (STREQ(me->mnt_type, MNTTAB_TYPE_NFS3)) { fs_ops = &nfs_ops; #endif /* MNTTAB_TYPE_NFS3 */ #ifdef MNTTAB_TYPE_LOFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_LOFS)) { fs_ops = &lofs_ops; #endif /* MNTTAB_TYPE_LOFS */ #ifdef MNTTAB_TYPE_CDFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_CDFS)) { fs_ops = &cdfs_ops; #endif /* MNTTAB_TYPE_CDFS */ #ifdef MNTTAB_TYPE_PCFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_PCFS)) { fs_ops = &pcfs_ops; #endif /* MNTTAB_TYPE_PCFS */ #ifdef MNTTAB_TYPE_MFS } else if (STREQ(me->mnt_type, MNTTAB_TYPE_MFS)) { /* * MFS entry. Fake with a symlink. */ fs_ops = &amfs_link_ops; #endif /* MNTTAB_TYPE_MFS */ } else { /* * Catch everything else with symlinks to * avoid recursive mounts. This is debatable... */ fs_ops = &amfs_link_ops; } /* * If we found something to do */ if (fs_ops) { mntfs *mf; am_opts mo; char *cp; cp = strchr(me->mnt_fsname, ':'); /* * Partially fake up an opts structure */ memset(&mo, 0, sizeof(mo)); mo.opt_rhost = 0; mo.opt_rfs = 0; if (cp) { *cp = '\0'; mo.opt_rhost = strdup(me->mnt_fsname); mo.opt_rfs = strdup(cp + 1); *cp = ':'; } else if (fs_ops->ffserver == find_nfs_srvr) { /* * Prototype 4.4 BSD used to end up here - * might as well keep the workaround for now */ plog(XLOG_WARNING, "NFS server entry assumed to be %s:/", me->mnt_fsname); mo.opt_rhost = strdup(me->mnt_fsname); mo.opt_rfs = strdup("/"); me->mnt_fsname = str3cat(me->mnt_fsname, mo.opt_rhost, ":", "/"); } mo.opt_fs = me->mnt_dir; mo.opt_opts = me->mnt_opts; /* * Make a new mounted filesystem */ mf = find_mntfs(fs_ops, &mo, me->mnt_dir, me->mnt_fsname, "", me->mnt_opts, ""); if (mf->mf_refc == 1) { mf->mf_flags |= MFF_RESTART | MFF_MOUNTED; mf->mf_error = 0; /* Already mounted correctly */ mf->mf_fo = 0; /* * If the restarted type is a link then * don't time out. */ if (fs_ops == &amfs_link_ops || fs_ops == &ufs_ops) mf->mf_flags |= MFF_RSTKEEP; if (fs_ops->fs_init) { /* * Don't care whether this worked since * it is checked again when the fs is * inherited. */ (void) (*fs_ops->fs_init) (mf); } plog(XLOG_INFO, "%s restarted fstype %s on %s", me->mnt_fsname, fs_ops->fs_type, me->mnt_dir); } else { /* Something strange happened - two mounts at the same place! */ free_mntfs(mf); } /* * Clean up mo */ if (mo.opt_rhost) XFREE(mo.opt_rhost); if (mo.opt_rfs) XFREE(mo.opt_rfs); } } /* * Free the mount list */ free_mntlist(ml); }
/* * Mount a sub-mount */ static int amfs_auto_mount(am_node *mp, mntfs *mf) { /* * Pseudo-directories are used to provide some structure * to the automounted directories instead * of putting them all in the top-level automount directory. * * Here, just increment the parent's link count. */ mp->am_parent->am_fattr.na_nlink++; /* * Info field of . means use parent's info field. * Historical - not documented. */ if (mf->mf_info[0] == '.' && mf->mf_info[1] == '\0') mf->mf_info = strealloc(mf->mf_info, mp->am_parent->am_mnt->mf_info); /* * Compute prefix: * * If there is an option prefix then use that else * If the parent had a prefix then use that with name * of this node appended else * Use the name of this node. * * That means if you want no prefix you must say so * in the map. */ if (mf->mf_fo->opt_pref) { /* allow pref:=null to set a real null prefix */ if (STREQ(mf->mf_fo->opt_pref, "null")) { mp->am_pref = strdup(""); } else { /* * the prefix specified as an option */ mp->am_pref = strdup(mf->mf_fo->opt_pref); } } else { /* * else the parent's prefix * followed by the name * followed by / */ char *ppref = mp->am_parent->am_pref; if (ppref == 0) ppref = ""; mp->am_pref = str3cat((char *) 0, ppref, mp->am_name, "/"); } #ifdef HAVE_FS_AUTOFS if (mf->mf_flags & MFF_IS_AUTOFS) { char opts[SIZEOF_OPTS]; int error; autofs_get_opts(opts, sizeof(opts), mp->am_autofs_fh); /* now do the mount */ error = amfs_mount(mp, mf, opts); if (error) { errno = error; plog(XLOG_FATAL, "amfs_auto_mount: amfs_mount failed: %m"); return error; } } #endif /* HAVE_FS_AUTOFS */ /* * Attach a map cache */ amfs_mkcacheref(mf); return 0; }
int autofs_mount_fs(am_node *mp, mntfs *mf) { char *target, *target2 = NULL; int err = 0; if (mf->mf_flags & MFF_ON_AUTOFS) { if ((err = mkdir(mp->am_path, 0555))) return errno; } /* * For sublinks, we could end up here with an already mounted f/s. * Don't do anything in that case. */ if (!(mf->mf_flags & MFF_MOUNTED)) err = mf->mf_ops->mount_fs(mp, mf); if (err) { if (mf->mf_flags & MFF_ON_AUTOFS) rmdir(mp->am_path); return err; } if (mf->mf_flags & MFF_ON_AUTOFS) /* Nothing else to do */ return 0; if (mp->am_link) target = mp->am_link; else target = mf->mf_fo->opt_fs; #ifdef MNT2_GEN_OPT_BIND if (bind_works && gopt.flags & CFM_AUTOFS_USE_LOFS) { struct stat buf; /* * HACK ALERT! * * Since the bind mount mechanism doesn't allow mountpoint crossing, * we _must_ use symlinks for the host mount case. Otherwise we end up * with a bunch of empty mountpoints... */ if (mf->mf_ops == &amfs_host_ops) goto use_symlink; if (target[0] != '/') target2 = str3cat(NULL, mp->am_parent->am_path, "/", target); else target2 = strdup(target); /* * We need to stat() the destination, because the bind mount does not * follow symlinks and/or allow for non-existent destinations. * We fall back to symlinks if there are problems. * * We also need to temporarily change pgrp, otherwise our stat() won't * trigger whatever cascading mounts are needed. * * WARNING: we will deadlock if this function is called from the master * amd process and it happens to trigger another auto mount. Therefore, * this function should be called only from a child amd process, or * at the very least it should not be called from the parent unless we * know for sure that it won't cause a recursive mount. We refuse to * cause the recursive mount anyway if called from the parent amd. */ if (!foreground) { pid_t pgrp = getpgrp(); setpgrp(); err = stat(target2, &buf); if ((err = setpgid(0, pgrp))) { plog(XLOG_ERROR, "autofs: cannot restore pgrp: %s", strerror(errno)); plog(XLOG_ERROR, "autofs: aborting the mount"); goto out; } if (err) goto use_symlink; } if ((err = lstat(target2, &buf))) goto use_symlink; if (S_ISLNK(buf.st_mode)) goto use_symlink; plog(XLOG_INFO, "autofs: bind-mounting %s -> %s", mp->am_path, target2); mkdir(mp->am_path, 0555); err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1); if (err) { rmdir(mp->am_path); plog(XLOG_INFO, "autofs: bind-mounting %s -> %s failed", mp->am_path, target2); goto use_symlink; } goto out; } #endif /* MNT2_GEN_OPT_BIND */ use_symlink: plog(XLOG_INFO, "autofs: symlinking %s -> %s", mp->am_path, target); err = symlink(target, mp->am_path); out: if (target2) XFREE(target2); if (err) return errno; return 0; }
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++; }