Esempio n. 1
0
/*
 * Add key and val to the map m.
 * key and val are assumed to be safe copies
 */
void
mapc_add_kv(mnt_map *m, char *key, char *val)
{
	kv **h;
	kv *n;
	int hash = kvhash_of(key);

#ifdef DEBUG
	dlog("add_kv: %s -> %s", key, val);
#endif

#ifdef HAS_REGEXP
	if (MAPC_ISRE(m)) {
		char keyb[MAXPATHLEN];
		regex_t *re;
		/*
		 * Make sure the string is bound to the start and end
		 */
		snprintf(keyb, sizeof(keyb), "^%s$", key);
		re = malloc(sizeof(*re));
		if (!re || regcomp(re, keyb, 0)) {
			free(re);
			plog(XLOG_USER, "error compiling RE \"%s\": %s", keyb);
			return;
		} else {
			free(key);
			key = (char *)re;
		}
	}
#endif

	h = &m->kvhash[hash];
	n = ALLOC(kv);
	n->key = key;
	n->val = val;
	n->next = *h;
	*h = n;
}
Esempio n. 2
0
static void
mapc_repl_kv(mnt_map *m, char *key, char *val)
{
  kv *k;

  /*
   * Compute the hash table offset
   */
  k = m->kvhash[kvhash_of(key)];

  /*
   * Scan the linked list for the key
   */
  while (k && !FSTREQ(k->key, key))
    k = k->next;

  if (k) {
    XFREE(k->val);
    k->val = val;
  } else {
    mapc_add_kv(m, key, val);
  }
}
Esempio n. 3
0
/*
 * Search the map for the key.
 * Put a safe copy in *pval or return
 * an error code
 */
int
mapc_meta_search(mnt_map *m, char *key, char **pval, int recurse)
{
	int error = 0;
	kv *k = 0;

	/*
	 * Firewall
	 */
	if (!m) {
		plog(XLOG_ERROR, "Null map request for %s", key);
		return ENOENT;
	}

	if (m->flags & MAPC_SYNC) {
		/*
		 * Get modify time...
		 */
		time_t t;
		error = (*m->mtime)(m->map_name, &t);
		if (error || t > m->modify) {
			m->modify = t;
			plog(XLOG_INFO, "Map %s is out of date", m->map_name);
			mapc_sync(m);
		}
	}

	if (!MAPC_ISRE(m)) {
		/*
		 * Compute the hash table offset
		 */
		k = m->kvhash[kvhash_of(key)];

		/*
		 * Scan the linked list for the key
		 */
		while (k && !FSTREQ(k->key, key)) k = k->next;

	}
#ifdef HAS_REGEXP
	else if (recurse == MREC_FULL) {
		/*
		 * Try for an RE match against the entire map.
		 * Note that this will be done in a "random"
		 * order.
		 */

		int i;

		for (i = 0; i < NKVHASH; i++) {
			k = m->kvhash[i];
			while (k) {
				if (regexec((regex_t *)k->key, key,
				    0, NULL, 0) == 0)
					break;
				k = k->next;
			}
			if (k)
				break;
		}
	}
#endif

	/*
	 * If found then take a copy
	 */
	if (k) {
		if (k->val)
			*pval = strdup(k->val);
		else
			error = ENOENT;
	} else if (m->alloc >= MAPC_ALL) {
		/*
		 * If the entire map is cached then this
		 * key does not exist.
		 */
		error = ENOENT;
	} else {
		/*
		 * Otherwise search the map.  If we are
		 * in incremental mode then add the key
		 * to the cache.
		 */
		error = search_map(m, key, pval);
		if (!error && m->alloc == MAPC_INC)
			mapc_add_kv(m, strdup(key), strdup(*pval));
	}

	/*
	 * If an error, and a wildcard exists,
	 * and the key is not internal then
	 * return a copy of the wildcard.
	 */
	if (error > 0) {
		if (recurse == MREC_FULL && !MAPC_ISRE(m)) {
			char wildname[MAXPATHLEN];
			char *subp;
			if (*key == '/')
				return error;
			/*
			 * Keep chopping sub-directories from the RHS
			 * and replacing with "/ *" and repeat the lookup.
			 * For example:
			 * "src/gnu/gcc" -> "src / gnu / *" -> "src / *"
			 */
			strlcpy(wildname, key, sizeof wildname);
			while (error && (subp = strrchr(wildname, '/'))) {
				strlcpy(subp, "/*", 3);
#ifdef DEBUG
				dlog("mapc recurses on %s", wildname);
#endif
				error = mapc_meta_search(m, wildname, pval, MREC_PART);
				if (error)
					*subp = 0;
			}
			if (error > 0 && m->wildcard) {
				*pval = strdup(m->wildcard);
				error = 0;
			}
		}
	}

	return error;
}
Esempio n. 4
0
/*
 * Add key and val to the map m.
 * key and val are assumed to be safe copies
 */
void
mapc_add_kv(mnt_map *m, char *key, char *val)
{
  kv **h;
  kv *n;
  int hash = kvhash_of(key);
#ifdef HAVE_REGEXEC
  regex_t re;
#endif /* HAVE_REGEXEC */

  dlog("add_kv: %s -> %s", key, val);

  if (val != NULL && strchr(val, '\n') != NULL) {
    /*
     * If the entry value contains multiple lines we need to break
     * them up and add them recursively.  This is a workaround to
     * support Sun style multi-mounts.  Amd converts Sun style
     * mulit-mounts to type:=auto.  The problem is that Sun packs all
     * the entries on one line.  When Amd does the conversion it puts
     * each type:=auto entry on the same line separated by '\n'.
     */
    char *entry, *tok;

    /*
     * The first line should contain the first entry.  The key for
     * this entry is the key passed into this function.
     */
    if ((tok = strtok(val, "\n")) != NULL) {
      mapc_add_kv(m, key, xstrdup(tok));
    }

    /*
     * For the rest of the entries we need to tokenize them by '\n'
     * and separate the keys from there entries.
     */
    while ((tok = strtok(NULL, "\n")) != NULL) {
      key = tok;
      /* find the entry */
      for (entry = key; *entry && !isspace((unsigned char)*entry); entry++);
      if (*entry) {
	*entry++ = '\0';
      }

      mapc_add_kv(m, xstrdup(key), xstrdup(entry));
    }

    XFREE(val);
    return;
  }

#ifdef HAVE_REGEXEC
  if (MAPC_ISRE(m)) {
    char pattern[MAXPATHLEN];
    int retval;

    /*
     * Make sure the string is bound to the start and end
     */
    xsnprintf(pattern, sizeof(pattern), "^%s$", key);
    retval = regcomp(&re, pattern, REG_ICASE);
    if (retval != 0) {
      char errstr[256];

      /* XXX: this code was recently ported, and must be tested -Erez */
      errstr[0] = '\0';
      regerror(retval, &re, errstr, 256);
      plog(XLOG_USER, "error compiling RE \"%s\": %s", pattern, errstr);
      return;
    }
  } else
    memset(&re, 0, sizeof(re));
#endif /* HAVE_REGEXEC */

  h = &m->kvhash[hash];
  n = ALLOC(struct kv);
  n->key = key;
#ifdef HAVE_REGEXEC
  memcpy(&n->re, &re, sizeof(regex_t));
#endif /* HAVE_REGEXEC */
  n->val = val;
  n->next = *h;
  *h = n;
  m->nentries++;
}