Пример #1
0
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;
}
Пример #2
0
/*
 * 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);
}
Пример #3
0
/*
 * 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);
}
Пример #4
0
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;
}
Пример #5
0
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;
}
Пример #6
0
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 ");
}
Пример #7
0
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);
}
Пример #8
0
/*
 * 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);
}
Пример #9
0
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;
}
Пример #10
0
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;
  }
Пример #11
0
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;
}
Пример #12
0
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;
}
Пример #13
0
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;
}
Пример #14
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++;
}
Пример #15
0
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++;
}
Пример #16
0
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);
}
Пример #17
0
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;
}
Пример #18
0
/*
 * 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);
}
Пример #19
0
/*
 * 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;
}
Пример #20
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;
}
Пример #21
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++;
}