예제 #1
0
static bool add_field_from_ldif(TALLOC_CTX *mem_ctx, struct ldb_message *ldif,
				const char ***fields, const char *field,
				bool mandatory)
{
	const char *val = ldb_msg_find_attr_as_string(ldif, field, "");
	if (strlen(val) == 0) {
		if (mandatory) {
			DEBUG(0, ("%s value hasn't been found! malformed ldif?",
				  field));
		}
		return false;
	}
	char *end;
	int intval = strtol(val, &end, 10);
	if (end && strlen(val) == (end - val)) {
		*fields = str_list_add(*fields,
				       talloc_asprintf(mem_ctx, "%s=%d", field,
						       intval));
	} else {
		*fields = str_list_add(*fields,
				       talloc_asprintf(mem_ctx, "%s='%s'",
						       field, val));
	}
	return true;
}
예제 #2
0
/**
  Table fields:
    * Mandatory fields:
        * `type` TINYINT(1)
        * `propType` INT(10) unsigned
        * `oleguid` VARCHAR(255)
        * `mappedId` INT(10) unsigned
    * Optional fields:
        * `propId` INT(10) unsigned
        * `propName` VARCHAR(255)
        * `oom` VARCHAR(255)
        * `canonical` VARCHAR(255)
 */
static bool insert_ldif_msg(MYSQL *conn, struct ldb_message *ldif)
{
	const char *val = ldb_msg_find_attr_as_string(ldif, "objectClass", "");
	if (strlen(val) < strlen("MNID_ID")) {
		// It's not a valid entry, ignore it
		return true;
	}
	TALLOC_CTX *mem_ctx = talloc_zero(NULL, TALLOC_CTX);
	const char **fields = (const char **) str_list_make_empty(mem_ctx);

	// Optional fields
	add_field_from_ldif(mem_ctx, ldif, &fields, "propId", false);
	add_field_from_ldif(mem_ctx, ldif, &fields, "propName", false);
	add_field_from_ldif(mem_ctx, ldif, &fields, "oom", false);
	add_field_from_ldif(mem_ctx, ldif, &fields, "canonical", false);
	// Mandatory fields
	// oleguid and mappedId
	if (!add_field_from_ldif(mem_ctx, ldif, &fields, "oleguid", true) ||
	    !add_field_from_ldif(mem_ctx, ldif, &fields, "mappedId", true)) {
		return false;
	}
	// type
	int type;
	if (strcmp(val, "MNID_STRING") == 0) {
		type = MNID_STRING;
	} else if (strcmp(val, "MNID_ID") == 0) {
		type = MNID_ID;
	} else {
		DEBUG(0, ("Invalid objectClass %s", val));
		return false;
	}
	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "type=%d", type));
	// propType: it could be either an integer or a constant PT_*, we have
	//           to store it as an integer
	val = ldb_msg_find_attr_as_string(ldif, "propType", "");
	if (strlen(val) == 0) {
		DEBUG(0, ("propType value hasn't been found! malformed ldif?"));
		return false;
	}
	int propType;
	if (isalpha(val[0])) {
		propType = mapistore_namedprops_prop_type_from_string(val);
		if (propType == -1) {
			DEBUG(0, ("Invalid propType %s", val));
			return false;
		}
	} else {
		propType = strtol(val, NULL, 10);
	}
	fields = str_list_add(fields,
			      talloc_asprintf(mem_ctx, "propType=%d", propType));
	// Done, we have all fields on fields array
	char *fields_sql = str_list_join(mem_ctx, fields, ',');
	char *sql = talloc_asprintf(mem_ctx,
			"INSERT INTO " NAMEDPROPS_MYSQL_TABLE " SET %s", fields_sql);
	mysql_query(conn, sql);
	talloc_free(mem_ctx);
	return true;
}
예제 #3
0
파일: pvremove.c 프로젝트: Distrotech/LVM2
int pvremove(struct cmd_context *cmd, int argc, char **argv)
{
	int i;
	unsigned force_count;
	unsigned prompt;
	struct dm_list pv_names;

	if (!argc) {
		log_error("Please enter a physical volume path");
		return EINVALID_CMD_LINE;
	}

	force_count = arg_count(cmd, force_ARG);
	prompt = arg_count(cmd, yes_ARG);

	dm_list_init(&pv_names);

	/* Needed to change the set of orphan PVs. */
	if (!lockd_gl(cmd, "ex", 0))
		return_ECMD_FAILED;

	for (i = 0; i < argc; i++) {
		dm_unescape_colons_and_at_signs(argv[i], NULL, NULL);
		if (!str_list_add(cmd->mem, &pv_names, argv[i]))
			return_ECMD_FAILED;
	}

	if (!pvremove_many(cmd, &pv_names, force_count, prompt))
		return_ECMD_FAILED;

	return ECMD_PROCESSED;
}
예제 #4
0
static str_list_type
dir_list_search_list P3C(str_llist_type *, dirs,  const_string*, names,
                         boolean, search_all)
{
  str_llist_elt_type *elt;
  str_list_type ret;
  unsigned allocated = INIT_ALLOC;
  string potential = XTALLOC(allocated, char);

  ret = str_list_init ();

  for (elt = *dirs; elt; elt = STR_LLIST_NEXT(*elt)) {
      const_string dir = STR_LLIST (*elt);
      unsigned dir_len = strlen (dir);
      int i;
      
      for (i = 0; names[i]; i++) {
          const_string name = names[i];
          unsigned name_len;

          /* Don't bother with absolute & explicit relative. */
          if (kpse_absolute_p(name, true))
              continue;
          
          name_len = strlen(name);

          while (dir_len + name_len + 1 > allocated) {
              allocated += allocated;
              XRETALLOC (potential, allocated, char);
          }

          strcpy (potential, dir);
          strcat (potential+dir_len, name);

          if (kpse_readable_file (potential)) {
              str_list_add (&ret, potential);

              /* Move this element towards the top of the list.  */
              str_llist_float (dirs, elt);

              /* If caller only wanted one file returned, no need to
                 terminate the list with NULL; the caller knows to only look
                 at the first element.  */
              if (!search_all)
                  return ret;

              /* Start new filename. */
              allocated = INIT_ALLOC;
              potential = XTALLOC(allocated, char);
          }
      }
  }

  /* If we get here, either we didn't find any files, or we were finding
     all the files.  But we're done with the last filename, anyway.  */
  free (potential);
  
  return ret;
}
예제 #5
0
파일: hash.c 프로젝트: luigiScarso/mflua
hash_lookup P2C(hash_table_type, table,  const_string, key)
{
  hash_element_type *p;
  str_list_type ret;
  unsigned n = hash (table, key);
  ret = str_list_init ();
  
  /* Look at everything in this bucket.  */
  for (p = table.buckets[n]; p != NULL; p = p->next)
    if (FILESTRCASEEQ (key, p->key))
      /* Cast because the general str_list_type shouldn't force const data.  */
      str_list_add (&ret, (string) p->value);
  
  /* If we found anything, mark end of list with null.  */
  if (STR_LIST (ret))
    str_list_add (&ret, NULL);

#ifdef KPSE_DEBUG
  if (KPSE_DEBUG_P (KPSE_DEBUG_HASH))
    {
      DEBUGF1 ("hash_lookup(%s) =>", key);
      if (!STR_LIST (ret))
        fputs (" (nil)\n", stderr);
      else
        {
          string *r;
          for (r = STR_LIST (ret); *r; r++)
            {
              putc (' ', stderr);
              if (kpse_debug_hash_lookup_int)
                fprintf (stderr, "%ld", (long) *r);
              else
                fputs (*r, stderr);
            }
          putc ('\n', stderr);
        }
      fflush (stderr);
    }
#endif

  return STR_LIST (ret);
}
예제 #6
0
파일: expand.c 프로젝트: luigiScarso/mflua
/* ... */
static void expand_append P3C(str_list_type*, partial,
                              const_string, text, const_string, p)
{
    string new_string;
    unsigned len;
    str_list_type tmp;
    tmp = str_list_init();
    len = p - text;
    new_string = (string)xmalloc(len+1);
    strncpy(new_string, text, len);
    new_string[len]=0;
    str_list_add(&tmp, new_string);
    str_list_concat_elements(partial, tmp);
}
int read_tags(struct dm_pool *mem, struct dm_list *tags, struct config_value *cv)
{
	if (cv->type == CFG_EMPTY_ARRAY)
		return 1;

	while (cv) {
		if (cv->type != CFG_STRING) {
			log_error("Found a tag that is not a string");
			return 0;
		}

		if (!str_list_add(mem, tags, dm_pool_strdup(mem, cv->v.str)))
			return_0;

		cv = cv->next;
	}

	return 1;
}
예제 #8
0
static str_list_type
absolute_search P1C(string, name)
{
  str_list_type ret_list;
  string found = kpse_readable_file (name);
  
  /* Some old compilers can't initialize structs.  */
  ret_list = str_list_init ();

  /* If NAME wasn't found, free the expansion.  */
  if (name != found)
    free (name);

  /* Add `found' to the return list even if it's null; that tells
     the caller we didn't find anything.  */
  str_list_add (&ret_list, found);
  
  return ret_list;
}
예제 #9
0
파일: banner.c 프로젝트: Einheri/wl500g
void
vsf_banner_dir_changed(struct vsf_session* p_sess, int ftpcode)
{
  struct mystr dir_str = INIT_MYSTR;
  /* Do nothing if .message support is off */
  if (!tunable_dirmessage_enable)
  {
    return;
  }
  if (p_sess->p_visited_dir_list == 0)
  {
    struct mystr_list the_list = INIT_STRLIST;
    p_sess->p_visited_dir_list = vsf_sysutil_malloc(sizeof(struct mystr_list));
    *p_sess->p_visited_dir_list = the_list;
  }
  str_getcwd(&dir_str);
  /* Do nothing if we already visited this directory */
  if (!str_list_contains_str(p_sess->p_visited_dir_list, &dir_str))
  {
    /* Just in case, cap the max. no of visited directories we'll remember */
    if (str_list_get_length(p_sess->p_visited_dir_list) <
        VSFTP_MAX_VISIT_REMEMBER)
    {
      str_list_add(p_sess->p_visited_dir_list, &dir_str, 0);
    }
    /* If we have a .message file, squirt it out prepended by the ftpcode and
     * the continuation mark '-'
     */
    {
      struct mystr msg_file_str = INIT_MYSTR;
      if (tunable_message_file)
      {
        (void) str_fileread(&msg_file_str, tunable_message_file,
                            VSFTP_MAX_MSGFILE_SIZE);
      }
      vsf_banner_write(p_sess, &msg_file_str, ftpcode);
      str_free(&msg_file_str);
    }
  }
  str_free(&dir_str);
}
예제 #10
0
static enum mapistore_error create_id(struct namedprops_context *self,
				      struct MAPINAMEID nameid,
				      uint16_t mapped_id)
{
	TALLOC_CTX *mem_ctx = talloc_zero(NULL, TALLOC_CTX);
	const char **fields = (const char **) str_list_make_empty(mem_ctx);

	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "type=%d",
						      nameid.ulKind));
	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "propType=%d",
						      PT_NULL));
	char *guid = GUID_string(mem_ctx, &nameid.lpguid);
	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "oleguid='%s'",
						      guid));
	fields = str_list_add(fields, talloc_asprintf(mem_ctx, "mappedId=%u",
						      mapped_id));
	if (nameid.ulKind == MNID_ID) {
		fields = str_list_add(fields,
				      talloc_asprintf(mem_ctx, "propId=%u",
						      nameid.kind.lid));
	} else if (nameid.ulKind == MNID_STRING) {
		fields = str_list_add(fields,
				      talloc_asprintf(mem_ctx, "propName='%s'",
						      nameid.kind.lpwstr.Name));
	} else {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERROR, mem_ctx);
	}

	char *fields_sql = str_list_join(mem_ctx, fields, ',');
	char *sql = talloc_asprintf(mem_ctx,
		"INSERT INTO " NAMEDPROPS_MYSQL_TABLE " SET %s", fields_sql);
	DEBUG(5, ("Inserting record:\n%s\n", sql));
	MYSQL *conn = self->data;
	if (mysql_query(conn, sql) != 0) {
		MAPISTORE_RETVAL_IF(true, MAPISTORE_ERR_DATABASE_OPS, mem_ctx);
	}

	talloc_free(mem_ctx);
	return MAPISTORE_SUCCESS;
}
예제 #11
0
search_list P4C(const_string, path,  const_string*, names,
                boolean, must_exist,  boolean, all)
{
  str_list_type ret_list;
  const_string* namep;
  string elt;
  boolean done = false;

#ifdef __DJGPP__
  /* We will use `stat' heavily, so let's request for
     the fastest possible version of `stat', by telling
     it what members of struct stat do we really need.

     We need to set this on each call because this is a
     library function; the caller might need other options
     from `stat'.  Thus save the flags and restore them
     before exit.

     This call tells `stat' that we do NOT need to recognize
     executable files (neither by an extension nor by a magic
     signature); that we do NOT need time stamp of root directories;
     and that we do NOT need the write access bit in st_mode.

     Note that `kpse_set_progname' needs the EXEC bits,
     but it was already called by the time we get here.  */
  unsigned short save_djgpp_flags  = _djstat_flags;

  _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
		  | _STAT_ROOT_TIME | _STAT_WRITEBIT;
#endif

  ret_list = str_list_init();

  if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
    DEBUGF1  ("start search(files=[%s", *names);
    for (namep = names+1; *namep != NULL; namep++) {
      fputc(' ', stderr);
      fputs(*namep, stderr);
    }
    fprintf (stderr, "], must_exist=%d, find_all=%d, path=%s).\n",
             must_exist, all, path);
  }
  
  /* No need to do any expansion on names.  */

  for (namep = names; *namep; namep++) {
      if (kpse_absolute_p(*namep, true) && kpse_readable_file(*namep)) {
          str_list_add(&ret_list, xstrdup(*namep));
          /* I know, I know... */
          goto out;
      }
  }

  /* Look at each path element in turn. */
  for (elt = kpse_path_element (path); !done && elt;
       elt = kpse_path_element (NULL))
  {
    str_list_type *found;
    boolean allow_disk_search = true;
    if (elt[0] == '!' && elt[1] == '!') {
      /* !! magic -> disallow disk searches. */
      allow_disk_search = false;
      elt += 2;
    }

    /* See elt-dirs.c for side effects of this function. */
    kpse_normalize_path(elt);

    /* Try ls-R, unless we're searching for texmf.cnf. */
    found = first_search ? NULL : kpse_db_search_list(names, elt, all);

    /* Search the filesystem if (1) the path spec allows it, and either
         (2a) we are searching for texmf.cnf ; or
         (2b) no db exists; or 
         (2c) no db's are relevant to this elt; or
         (3) MUST_EXIST && NAME was not in the db.
       In (2*), `found' will be NULL.
       In (3),  `found' will be an empty list. */
    if (allow_disk_search && (!found || (must_exist && !STR_LIST(*found)))) {
      str_llist_type *dirs = kpse_element_dirs (elt);
      if (dirs && *dirs) {
        if (!found)
          found = XTALLOC1 (str_list_type);
        *found = dir_list_search_list (dirs, names, all);
      }
    }

    /* Did we find anything? */
    if (found && STR_LIST (*found)) {
      if (all) {
        str_list_concat (&ret_list, *found);
      } else {
        str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
        done = true;
      }
    }
  }

 out:
  if (STR_LIST_LENGTH (ret_list) == 0
      || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
    str_list_add (&ret_list, NULL);

  if (first_search) {
    first_search = false;
  } else {
    /* Record the filenames we found, if desired.  And wrap them in a
       debugging line if we're doing that.  */
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH)) {
      DEBUGF1 ("search([%s", *names);
      for (namep = names+1; *namep != NULL; namep++) {
        fputc(' ', stderr);
        fputs(*namep, stderr);
      }
      fputs ("]) =>", stderr);
    }
    log_search (ret_list);
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
      putc ('\n', stderr);
  }

#ifdef __DJGPP__
  /* Undo any side effects.  */
  _djstat_flags = save_djgpp_flags;
#endif
  
  return STR_LIST (ret_list);
}
예제 #12
0
파일: db.c 프로젝트: clerkma/texlive-mobile
void
kpathsea_init_db (kpathsea kpse)
{
  const_string db_path;
  string *db_files;
  string *orig_db_files;
  str_list_type unique_list;
  int dbi;
  boolean ok = false;

  assert (sizeof(DB_NAME) == sizeof(DB_NAME_LC));

  db_path = kpathsea_init_format (kpse, kpse_db_format);
  db_files = kpathsea_path_search_list_generic (kpse, db_path, db_names,
                                                true, true);
  orig_db_files = db_files;
  
  /* Mac OS X and others can use a case-insensitive, case-preserving
     filesystem by default, in which case ls-R and ls-r point to the
     same file.  Also, Windows is case-insensitive.  In these cases,
     we want to avoid reading the same file multiple times. */
  dbi = 0;
  unique_list = str_list_init ();
  
  while (db_files[dbi] != NULL) {
    string path1 = db_files[dbi];
    string path2 = db_files[dbi + 1];

    /* first-pass check in case path1/path2 aren't even
       potentially equal; mainly in case the order from
       kpathsea_path_search_list_generic changes. */
    if (path2
        && strcasecmp (path1, path2) == 0
        && same_file_p (path1, path2)) {
      /* they are the same, skip over path1, we'll add path2
         on the next iteration (when it's path1). */
#ifdef KPSE_DEBUG
      if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH)) {
        DEBUGF2 ("db:init(): skipping db same_file_p %s, will add %s.\n",
                 path1, path2);
      }
#endif
      free (path1);

    } else {
     /* they are not the same, add path1.  */
#ifdef KPSE_DEBUG
      if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH)) {
        DEBUGF1 ("db:init(): using db file %s.\n", path1);
      }
#endif
      str_list_add (&unique_list, path1);
    }

    /* could be more clever and increment by two, but then would
       have to avoid jumping off the end of db_files */
    dbi++;
  }
  
  /* always add a NULL terminator.  */
  str_list_add (&unique_list, NULL);
  
  free (orig_db_files);
  db_files = STR_LIST (unique_list);
  orig_db_files = db_files;

  /* Must do this after the path searching (which ends up calling
     kpse_db_search recursively), so kpse->db.buckets stays NULL.  */
  kpse->db = hash_create (DB_HASH_SIZE);

  while (db_files && *db_files) {
    if (db_build (kpse, &(kpse->db), *db_files))
      ok = true;
    free (*db_files);
    db_files++;
  }

  if (!ok) {
    /* If db can't be built, leave `size' nonzero (so we don't
       rebuild it), but clear `buckets' (so we don't look in it).  */
    free (kpse->db.buckets);
    kpse->db.buckets = NULL;
  }

  free (orig_db_files);

  /* Add the content of any alias databases.  There may exist more than
     one alias file along DB_NAME files.  This duplicates the above code
     -- should be a function.  */
  ok = false;
  db_files = kpathsea_all_path_search (kpse, db_path, ALIAS_NAME);
  orig_db_files = db_files;

  kpse->alias_db = hash_create (ALIAS_HASH_SIZE);

  while (db_files && *db_files) {
    if (alias_build (kpse, &(kpse->alias_db), *db_files))
      ok = true;
    free (*db_files);
    db_files++;
  }

  if (!ok) {
    free (kpse->alias_db.buckets);
    kpse->alias_db.buckets = NULL;
  }

  free (orig_db_files);
}
예제 #13
0
static int parse_str_list(const m_option_t* opt,const char *name, char *param, void* dst, int src) {
  int n = 0,len = strlen(opt->name);
  char *str;
  char *ptr = param, *last_ptr, **res;
  int op = OP_NONE;

  if(opt->name[len-1] == '*' && ((int)strlen(name) > len - 1)) {
    const char* n = &name[len-1];
    if(strcasecmp(n,"-add") == 0)
      op = OP_ADD;
    else if(strcasecmp(n,"-pre") == 0)
      op = OP_PRE;
    else if(strcasecmp(n,"-del") == 0)
      op = OP_DEL;
    else if(strcasecmp(n,"-clr") == 0)
      op = OP_CLR;
    else
      return M_OPT_UNKNOWN;
  }

  // Clear the list ??
  if(op == OP_CLR) {
    if(dst)
      free_str_list(dst);
    return 0;
  }

  // All other ops need a param
  if (param == NULL || strlen(param) == 0)
      return M_OPT_MISSING_PARAM;


  while(ptr[0] != '\0') {
    ptr = get_nextsep(ptr, LIST_SEPARATOR, 0);
    if(!ptr) {
      n++;
      break;
    }
    ptr++;
    n++;
  }
  if(n == 0)
    return M_OPT_INVALID;
  if( ((opt->flags & M_OPT_MIN) && (n < opt->min)) ||
      ((opt->flags & M_OPT_MAX) && (n > opt->max)) )
    return M_OPT_OUT_OF_RANGE;

  if(!dst) return 1;

  res = malloc((n+2)*sizeof(char*));
  ptr = str = strdup(param);
  n = 0;

  while(1) {
    last_ptr = ptr;
    ptr = get_nextsep(ptr, LIST_SEPARATOR, 1);
    if(!ptr) {
      res[n] = strdup(last_ptr);
      n++;
      break;
    }
    len = ptr - last_ptr;
    res[n] = malloc(len + 1);
    if(len) strncpy(res[n],last_ptr,len);
    res[n][len] = '\0';
    ptr++;
    n++;
  }
  res[n] = NULL;
  free(str);

  switch(op) {
  case OP_ADD:
    return str_list_add(res,n,dst,0);
  case OP_PRE:
    return str_list_add(res,n,dst,1);
  case OP_DEL:
    return str_list_del(res,n,dst);
  }

  if(VAL(dst))
    free_str_list(dst);
  VAL(dst) = res;

  return 1;
}
예제 #14
0
void
vsf_ls_populate_dir_list(const char* session_user,
                         struct mystr_list* p_list,
                         struct mystr_list* p_subdir_list,
                         struct vsf_sysutil_dir* p_dir,
                         const struct mystr* p_base_dir_str,
                         const struct mystr* p_option_str,
                         const struct mystr* p_filter_str,
                         int is_verbose)
{
    struct mystr dirline_str = INIT_MYSTR;
    struct mystr normalised_base_dir_str = INIT_MYSTR;
    struct str_locate_result loc_result;
    int a_option;
    int r_option;
    int t_option;
    int F_option;
    int do_stat = 0;
    long curr_time = 0;
    loc_result = str_locate_char(p_option_str, 'a');
    a_option = loc_result.found;
    loc_result = str_locate_char(p_option_str, 'r');
    r_option = loc_result.found;
    loc_result = str_locate_char(p_option_str, 't');
    t_option = loc_result.found;
    loc_result = str_locate_char(p_option_str, 'F');
    F_option = loc_result.found;
    loc_result = str_locate_char(p_option_str, 'l');
    if (loc_result.found)
    {
        is_verbose = 1;
    }
    /* Invert "reverse" arg for "-t", the time sorting */
    if (t_option)
    {
        r_option = !r_option;
    }
    if (is_verbose || t_option || F_option || p_subdir_list != 0)
    {
        do_stat = 1;
    }
    /* If the filter starts with a . then implicitly enable -a */
    if (!str_isempty(p_filter_str) && str_get_char_at(p_filter_str, 0) == '.')
    {
        a_option = 1;
    }
    /* "Normalise" the incoming base directory string by making sure it
     * ends in a '/' if it is nonempty
     */
    if (!str_equal_text(p_base_dir_str, "."))
    {
        str_copy(&normalised_base_dir_str, p_base_dir_str);
    }
    if (!str_isempty(&normalised_base_dir_str))
    {
        unsigned int len = str_getlen(&normalised_base_dir_str);
        if (str_get_char_at(&normalised_base_dir_str, len - 1) != '/')
        {
            str_append_char(&normalised_base_dir_str, '/');
        }
    }
    /* If we're going to need to do time comparisions, cache the local time */
    if (is_verbose)
    {
        curr_time = vsf_sysutil_get_time_sec();
    }
    while (1)
    {
        static struct mystr s_next_filename_str;
        static struct mystr s_next_path_and_filename_str;
        static struct vsf_sysutil_statbuf* s_p_statbuf;
        str_next_dirent(session_user, str_getbuf(p_base_dir_str), &s_next_filename_str, p_dir);
        if (!strcmp(str_getbuf(&s_next_filename_str), DENIED_DIR))
            continue;
        if (str_isempty(&s_next_filename_str))
        {
            break;
        }
        {
            unsigned int len = str_getlen(&s_next_filename_str);
            if (len > 0 && str_get_char_at(&s_next_filename_str, 0) == '.')
            {
                if (!a_option && !tunable_force_dot_files)
                {
                    continue;
                }
                if (!a_option &&
                        ((len == 2 && str_get_char_at(&s_next_filename_str, 1) == '.') ||
                         len == 1))
                {
                    continue;
                }
            }
        }
        /* Don't show hidden directory entries */
        if (!vsf_access_check_file_visible(&s_next_filename_str))
        {
            continue;
        }
#if 0
        /* If we have an ls option which is a filter, apply it */
        if (!str_isempty(p_filter_str))
        {
            unsigned int iters = 0;
            if (!vsf_filename_passes_filter(&s_next_filename_str, p_filter_str,
                                            &iters))
            {
                continue;
            }
        }
#endif
        /* Calculate the full path (relative to CWD) for lstat() and
         * output purposes
         */
        str_copy(&s_next_path_and_filename_str, &normalised_base_dir_str);
        str_append_str(&s_next_path_and_filename_str, &s_next_filename_str);
        if (do_stat)
        {
            /* lstat() the file. Of course there's a race condition - the
             * directory entry may have gone away whilst we read it, so
             * ignore failure to stat
             */
            int retval = str_lstat(&s_next_path_and_filename_str, &s_p_statbuf);
            if (vsf_sysutil_retval_is_error(retval))
            {
                continue;
            }
        }
        if (is_verbose)
        {
            static struct mystr s_final_file_str;
            /* If it's a damn symlink, we need to append the target */
            str_copy(&s_final_file_str, &s_next_filename_str);
            if (vsf_sysutil_statbuf_is_symlink(s_p_statbuf))
            {
                static struct mystr s_temp_str;
                int retval = str_readlink(&s_temp_str, &s_next_path_and_filename_str);
                if (retval == 0 && !str_isempty(&s_temp_str))
                {
                    str_append_text(&s_final_file_str, " -> ");
                    str_append_str(&s_final_file_str, &s_temp_str);
                }
            }
            if (F_option && vsf_sysutil_statbuf_is_dir(s_p_statbuf))
            {
                str_append_char(&s_final_file_str, '/');
            }
            build_dir_line(&dirline_str, &s_final_file_str, s_p_statbuf, curr_time);
        }
        else
        {
            char *ptr;
            /* Just emit the filenames - note, we prepend the directory for NLST
             * but not for LIST
             */
            str_copy(&dirline_str, &s_next_path_and_filename_str);
            if (F_option)
            {
                if (vsf_sysutil_statbuf_is_dir(s_p_statbuf))
                {
                    str_append_char(&dirline_str, '/');
                }
                else if (vsf_sysutil_statbuf_is_symlink(s_p_statbuf))
                {
                    str_append_char(&dirline_str, '@');
                }
            }
            str_append_text(&dirline_str, "\r\n");
            ptr = strstr(str_getbuf(&dirline_str), POOL_MOUNT_ROOT);
            if (ptr != NULL)
                str_alloc_text(&dirline_str, ptr + strlen(POOL_MOUNT_ROOT));
        }
        /* Add filename into our sorted list - sorting by filename or time. Also,
         * if we are required to, maintain a distinct list of direct
         * subdirectories.
         */
        {
            static struct mystr s_temp_str;
            const struct mystr* p_sort_str = 0;
            const struct mystr* p_sort_subdir_str = 0;
            if (!t_option)
            {
                p_sort_str = &s_next_filename_str;
            }
            else
            {
                str_alloc_text(&s_temp_str,
                               vsf_sysutil_statbuf_get_sortkey_mtime(s_p_statbuf));
                p_sort_str = &s_temp_str;
                p_sort_subdir_str = &s_temp_str;
            }
            str_list_add(p_list, &dirline_str, p_sort_str);
            if (p_subdir_list != 0 && vsf_sysutil_statbuf_is_dir(s_p_statbuf))
            {
                str_list_add(p_subdir_list, &s_next_filename_str, p_sort_subdir_str);
            }
        }
    } /* END: while(1) */
    str_list_sort(p_list, r_option);
    if (p_subdir_list != 0)
    {
        str_list_sort(p_subdir_list, r_option);
    }
    str_free(&dirline_str);
    str_free(&normalised_base_dir_str);
}
예제 #15
0
파일: basic.c 프로젝트: DavidMulder/samba
static bool test_search_rootDSE(struct ldap_connection *conn, const char **basedn,
	const char ***partitions)
{
	bool ret = true;
	struct ldap_message *msg, *result;
	struct ldap_request *req;
	int i;
	struct ldap_SearchResEntry *r;
	NTSTATUS status;

	printf("Testing RootDSE Search\n");

	*basedn = NULL;

	if (partitions != NULL) {
		*partitions = const_str_list(str_list_make_empty(conn));
	}

	msg = new_ldap_message(conn);
	if (!msg) {
		return false;
	}

	msg->type = LDAP_TAG_SearchRequest;
	msg->r.SearchRequest.basedn = "";
	msg->r.SearchRequest.scope = LDAP_SEARCH_SCOPE_BASE;
	msg->r.SearchRequest.deref = LDAP_DEREFERENCE_NEVER;
	msg->r.SearchRequest.timelimit = 0;
	msg->r.SearchRequest.sizelimit = 0;
	msg->r.SearchRequest.attributesonly = false;
	msg->r.SearchRequest.tree = ldb_parse_tree(msg, "(objectclass=*)");
	msg->r.SearchRequest.num_attributes = 0;
	msg->r.SearchRequest.attributes = NULL;

	req = ldap_request_send(conn, msg);
	if (req == NULL) {
		printf("Could not setup ldap search\n");
		return false;
	}

	status = ldap_result_one(req, &result, LDAP_TAG_SearchResultEntry);
	if (!NT_STATUS_IS_OK(status)) {
		printf("search failed - %s\n", nt_errstr(status));
		return false;
	}

	printf("received %d replies\n", req->num_replies);

	r = &result->r.SearchResultEntry;
		
	DEBUG(1,("\tdn: %s\n", r->dn));
	for (i=0; i<r->num_attributes; i++) {
		int j;
		for (j=0; j<r->attributes[i].num_values; j++) {
			DEBUG(1,("\t%s: %d %.*s\n", r->attributes[i].name,
				 (int)r->attributes[i].values[j].length,
				 (int)r->attributes[i].values[j].length,
				 (char *)r->attributes[i].values[j].data));
			if (!(*basedn) && 
			    strcasecmp("defaultNamingContext",r->attributes[i].name)==0) {
				*basedn = talloc_asprintf(conn, "%.*s",
							  (int)r->attributes[i].values[j].length,
							  (char *)r->attributes[i].values[j].data);
			}
			if ((partitions != NULL) &&
			    (strcasecmp("namingContexts", r->attributes[i].name) == 0)) {
				char *entry = talloc_asprintf(conn, "%.*s",
							      (int)r->attributes[i].values[j].length,
							      (char *)r->attributes[i].values[j].data);
				*partitions = str_list_add(*partitions, entry);
			}
		}
	}

	return ret;
}
예제 #16
0
/* kpse:lookup("plain.tex", {}) */
static int do_lua_kpathsea_lookup(lua_State * L, kpathsea kpse, int idx)
{
    int i;
    string ret = NULL;
    string *ret_list = NULL;
    const_string name = NULL;
    string user_path = NULL;
    boolean show_all = false;
    boolean must_exist = false;
    kpse_file_format_type user_format = kpse_last_format;
    int dpi = 600;
    str_list_type subdir_paths = { 0, NULL };
    unsigned saved_debug = kpse->debug;
    int saved_mktexpk = kpse->format_info[kpse_pk_format].program_enabled_p;
    int saved_mktexmf = kpse->format_info[kpse_mf_format].program_enabled_p;
    int saved_mktextex = kpse->format_info[kpse_tex_format].program_enabled_p;
    int saved_mktextfm = kpse->format_info[kpse_tfm_format].program_enabled_p;
    name = luaL_checkstring(L, idx);
    /* todo: fetch parameter values */

    if (lua_type(L, idx + 1) == LUA_TTABLE) {
        lua_pushstring(L, "format");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TSTRING) {
            int op = luaL_checkoption(L, -1, NULL, filetypenames);
            user_format = filetypes[op];
        }
        lua_pop(L, 1);
        lua_pushstring(L, "dpi");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TNUMBER) {
            dpi = (int) lua_tointeger(L, -1);
        }
        lua_pop(L, 1);
        lua_pushstring(L, "debug");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TNUMBER) {
            int d = 0;
            d = (int) lua_tointeger(L, -1);
            kpse->debug |= d;
        }
        lua_pop(L, 1);
        lua_pushstring(L, "path");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TSTRING) {
            user_path = xstrdup(lua_tostring(L, -1));
        }
        lua_pop(L, 1);
        lua_pushstring(L, "all");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TBOOLEAN) {
            show_all = lua_toboolean(L, -1);
        }
        lua_pop(L, 1);

        lua_pushstring(L, "mktexpk");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TBOOLEAN) {
            kpathsea_maketex_option(kpse, "pk", lua_toboolean(L, -1));
        }
        lua_pop(L, 1);

        lua_pushstring(L, "mktextex");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TBOOLEAN) {
            kpathsea_maketex_option(kpse, "tex", lua_toboolean(L, -1));
        }
        lua_pop(L, 1);

        lua_pushstring(L, "mktexmf");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TBOOLEAN) {
            kpathsea_maketex_option(kpse, "mf", lua_toboolean(L, -1));
        }
        lua_pop(L, 1);

        lua_pushstring(L, "mktextfm");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TBOOLEAN) {
            kpathsea_maketex_option(kpse, "tfm", lua_toboolean(L, -1));
        }
        lua_pop(L, 1);


        lua_pushstring(L, "mustexist");
        lua_gettable(L, idx + 1);
        if (lua_type(L, -1) == LUA_TBOOLEAN) {
            must_exist = lua_toboolean(L, -1);
        }
        lua_pop(L, 1);
        lua_pushstring(L, "subdir");
        lua_gettable(L, idx + 1);
        if (lua_istable(L, -1)) {
            lua_pushnil(L);
            while (lua_next(L, -2) != 0) {      /* numeric value */
                if (lua_type(L, -1) == LUA_TSTRING) {
                    char *s = xstrdup(lua_tostring(L, -1));
                    str_list_add(&subdir_paths, s);
                    xfree(s);
                }
                lua_pop(L, 1);
            }
        } else if (lua_type(L, -1) == LUA_TSTRING) {
            char *s = xstrdup(lua_tostring(L, -1));
            str_list_add(&subdir_paths, s);
            xfree(s);
        }
        lua_pop(L, 1);
        if (STR_LIST_LENGTH(subdir_paths) > 0) {
            show_all = 1;
        }
    }
    if (user_path) {
        /* Translate ; to : if that's our ENV_SEP.  See cnf.c.  */
        if (IS_ENV_SEP(':')) {
            string loc;
            for (loc = user_path; *loc; loc++) {
                if (*loc == ';')
                    *loc = ':';
            }
        }
        user_path = kpathsea_path_expand(kpse, user_path);
        if (show_all) {
            ret_list = kpathsea_all_path_search(kpse, user_path, name);
        } else {
            ret = kpathsea_path_search(kpse, user_path, name, must_exist);
        }
        free(user_path);
    } else {
        /* No user-specified search path, check user format or guess from NAME.  */
        kpse_file_format_type fmt;
        if (user_format != kpse_last_format)
            fmt = user_format;
        else
            fmt = find_format(kpse, name, true);

        switch (fmt) {
        case kpse_pk_format:
        case kpse_gf_format:
        case kpse_any_glyph_format:
            {
                kpse_glyph_file_type glyph_ret;
                string temp = remove_suffix (name);
                /* Try to extract the resolution from the name.  */
                unsigned local_dpi = find_dpi(name);
                if (!local_dpi)
                    local_dpi = (unsigned) dpi;
                ret =
                    kpathsea_find_glyph(kpse, temp, local_dpi,
                                        fmt, &glyph_ret);
                if (temp != name)
                    free (temp);
            }
            break;

        case kpse_last_format:
            /* If the suffix isn't recognized, assume it's a tex file. */
            fmt = kpse_tex_format;
            /* fall through */

        default:
            if (show_all) {
                ret_list =
                    kpathsea_find_file_generic(kpse, name, fmt, must_exist,
                                               true);
            } else {
                ret = kpathsea_find_file(kpse, name, fmt, must_exist);
            }
        }
    }

    /* Turn single return into a null-terminated list for uniform treatment.  */
    if (ret) {
        ret_list = XTALLOC(2, string);
        ret_list[0] = ret;
        ret_list[1] = NULL;
    }

    /* Filter by subdirectories, if specified.  */
    if (STR_LIST_LENGTH(subdir_paths) > 0) {
        string *new_list = subdir_match(subdir_paths, ret_list);
        free(ret_list);
        ret_list = new_list;
    }
    kpse->debug = saved_debug;
    kpse->format_info[kpse_pk_format].program_enabled_p = saved_mktexpk;
    kpse->format_info[kpse_mf_format].program_enabled_p = saved_mktexmf;
    kpse->format_info[kpse_tex_format].program_enabled_p = saved_mktextex;
    kpse->format_info[kpse_tfm_format].program_enabled_p = saved_mktextfm;

    /* Print output.  */
    i = 0;
    if (ret_list) {
        for (; ret_list[i]; i++) {
            lua_pushstring(L, ret_list[i]);
        }
        free(ret_list);
    }
    if (i == 0) {
        i++;
        lua_pushnil(L);
    }
    return i;
}
예제 #17
0
int LOCAL_XFORM(main, the_session)(void *session) {
	struct vsf_session_old *old_session = (struct vsf_session_old *) stackvars_get_local("main", "the_session");
	assert(old_session);
	struct vsf_session *new_session = (struct vsf_session *) session; 

/* copy control connection */
	if (old_session->p_local_addr != NULL) {
		new_session->p_local_addr = malloc(sizeof(struct sockaddr_in));
		memcpy(new_session->p_local_addr, old_session->p_local_addr, sizeof(struct sockaddr_in)); 
		free(old_session->p_local_addr);
	}

	if (old_session->p_remote_addr != NULL) {
		new_session->p_remote_addr = malloc(sizeof(struct sockaddr_in)); 
		memcpy(new_session->p_remote_addr, old_session->p_remote_addr, sizeof(struct sockaddr_in));
		free(old_session->p_remote_addr);
	}

	/* copy data connection */
	new_session->pasv_listen_fd = old_session->pasv_listen_fd;
	if (old_session->p_port_sockaddr != NULL) {
		new_session->p_port_sockaddr = malloc(sizeof(struct sockaddr_in));
		memcpy(new_session->p_port_sockaddr, old_session->p_port_sockaddr, sizeof(struct sockaddr_in));
		free(old_session->p_port_sockaddr);
	}
	new_session->data_fd = old_session->data_fd;
	new_session->data_progress = old_session->data_progress;
	new_session->bw_rate_max = old_session->bw_rate_max;
	new_session->bw_send_start_sec = old_session->bw_send_start_sec;
	new_session->bw_send_start_usec = old_session->bw_send_start_usec;

	/* copy login details */
	new_session->is_anonymous = old_session->is_anonymous;
	str_copy(&(new_session->user_str), &(old_session->user_str));
	str_copy(&(new_session->anon_pass_str), &(old_session->anon_pass_str));
	
	/* copy ftp protocol state */
	new_session->restart_pos = old_session->restart_pos;
	new_session->is_ascii = old_session->is_ascii;
	str_copy(&(new_session->rnfr_filename_str), &(old_session->rnfr_filename_str));
	new_session->abor_received = old_session->abor_received;

	/* copy ftp session state */
	struct mystr_list the_list = INIT_STRLIST;
  new_session->p_visited_dir_list = vsf_sysutil_malloc(sizeof(struct mystr_list));
  *new_session->p_visited_dir_list = the_list;

	struct mystr_list *mystr_l = old_session->p_visited_dir_list;
	if (mystr_l != NULL) {
		int num_nodes = mystr_l->list_len;
		new_session->p_visited_dir_list->list_len = 0;
		new_session->p_visited_dir_list->alloc_len = mystr_l->alloc_len; /* save some reallocs */
		new_session->p_visited_dir_list->p_nodes = (void*) 0;
		int i;	
		for (i = 0; i < num_nodes; i++) {
			str_list_add(new_session->p_visited_dir_list, &(mystr_l->p_nodes[i].str),
					&(mystr_l->p_nodes[i].sort_key_str));
		}
	}

	/* copy userids */
	new_session->anon_ftp_uid = old_session->anon_ftp_uid;
	new_session->anon_upload_chown_uid;
		/* guest_user_uid added; main should init it properly */

	/* copy cache */
	str_copy(&(new_session->banned_email_str), &(old_session->banned_email_str));
	str_copy(&(new_session->userlist_str), &(old_session->userlist_str));
	str_copy(&(new_session->banner_str), &(old_session->banner_str));
	new_session->tcp_wrapper_ok = old_session->tcp_wrapper_ok;

	/* copy logging related details */
		/* let main + logging.c handle init of xferlog_fd and log_fd */
	str_copy(&(new_session->remote_ip_str), &(old_session->remote_ip_str));
	new_session->log_type = old_session->log_type;	
	new_session->log_start_sec = old_session->log_start_sec;
	new_session->log_start_usec = old_session->log_start_usec;
	str_copy(&(new_session->log_str), &(old_session->log_str));
	new_session->transfer_size = old_session->transfer_size;

	/* copy buffers */
	str_copy(&(new_session->ftp_cmd_str), &(old_session->ftp_cmd_str));
	str_copy(&(new_session->ftp_arg_str), &(old_session->ftp_arg_str));

	/* copy parent<->child comms channel */	
	new_session->parent_fd = old_session->parent_fd;
	new_session->child_fd = old_session->child_fd;

	/* copy other details */
	new_session->num_clients = old_session->num_clients;
	new_session->num_this_ip = old_session->num_this_ip;

	return 1;
}
예제 #18
0
파일: db.c 프로젝트: starseeker/ModTeX
str_list_type *
kpathsea_db_search_list (kpathsea kpse, string* names,
                         const_string path_elt, boolean all)
{
  const_string *db_dirs, *orig_dirs;
  const_string last_slash, name, path;
  string temp_str = NULL;
  boolean done;
  unsigned e;
  const_string *aliases, *r;
  int n;
  str_list_type *ret = NULL;
  boolean relevant = false;

  /* If we failed to build the database (or if this is the recursive
     call to build the db path), quit.  */
  if (kpse->db.buckets == NULL)
    return NULL;

  /* Don't bother doing any lookups if this `path_elt' isn't covered by
     any of database directories.  We do this not so much because the
     extra couple of hash lookups matter -- they don't -- but rather
     because we want to return NULL in this case, so path_search can
     know to do a disk search.  */
  for (e = 0; !relevant && e < STR_LIST_LENGTH (kpse->db_dir_list); e++) {
    relevant = elt_in_db (STR_LIST_ELT (kpse->db_dir_list, e), path_elt);
  }
  if (!relevant)
    return NULL;

  done = false;
  ret = XTALLOC1 (str_list_type);
  *ret = str_list_init ();

  /* Handle each name. */
  for (n = 0; !done && names[n]; n++) {
      name = names[n];

      /* Absolute names should have been caught in our caller. */
      if (kpathsea_absolute_p(kpse, name, true))
          continue;

      /* When tex-glyph.c calls us looking for, e.g., dpi600/cmr10.pk, we
         won't find it unless we change NAME to just `cmr10.pk' and append
         `/dpi600' to PATH_ELT.  We are justified in using a literal `/'
         here, since that's what tex-glyph.c unconditionally uses in
         DPI_BITMAP_SPEC.  But don't do anything if the / begins NAME; that
         should never happen.  */
      last_slash = strrchr (name, '/');
      if (last_slash && last_slash != name) {
          unsigned len = last_slash - name + 1;
          string dir_part = (string)xmalloc (len);
          strncpy (dir_part, name, len - 1);
          dir_part[len - 1] = 0;
          path = temp_str = concat3 (path_elt, "/", dir_part);
          name = last_slash + 1;
          free (dir_part);
      } else {
          path = path_elt;
      }

      /* If we have aliases for this name, use them.  */
      if (kpse->alias_db.buckets)
          aliases = hash_lookup (kpse->alias_db, name);
      else
          aliases = NULL;

      if (!aliases) {
          aliases = XTALLOC1 (const_string);
          aliases[0] = NULL;
      }
      {  /* Push aliases up by one and insert the original name at front.  */
          unsigned i;
          unsigned len = 1; /* Have NULL element already allocated.  */
          for (r = aliases; *r; r++)
              len++;
          aliases = (const_string *) xrealloc ((void *) aliases,
                                               (len + 1) * sizeof(const_string));
          for (i = len; i > 0; i--) {
              aliases[i] = aliases[i - 1];
          }
          aliases[0] = name;
      }

      for (r = aliases; !done && *r; r++) {
          const_string ctry = *r;

          /* We have an ls-R db.  Look up `try'.  */
          orig_dirs = db_dirs = hash_lookup (kpse->db, ctry);

          /* For each filename found, see if it matches the path element.  For
             example, if we have .../cx/cmr10.300pk and .../ricoh/cmr10.300pk,
             and the path looks like .../cx, we don't want the ricoh file.  */
          while (!done && db_dirs && *db_dirs) {
            string db_file = concat (*db_dirs, ctry);
            boolean matched = match (db_file, path);

#ifdef KPSE_DEBUG
            if (KPATHSEA_DEBUG_P (KPSE_DEBUG_SEARCH))
              DEBUGF3 ("db:match(%s,%s) = %d\n", db_file, path, matched);
#endif

            /* We got a hit in the database.  Now see if the file actually
               exists, possibly under an alias.  */
            if (matched) {
              string found = NULL;
              if (kpathsea_readable_file (kpse, db_file)) {
                found = db_file;

              } else {
                const_string *a;

                free (db_file); /* `db_file' wasn't on disk.  */

                /* The hit in the DB doesn't exist in disk.  Now try all its
                   aliases.  For example, suppose we have a hierarchy on CD,
                   thus `mf.bas', but ls-R contains `mf.base'.  Find it anyway.
                   Could probably work around this with aliases, but
                   this is pretty easy and shouldn't hurt.  The upshot is that
                   if one of the aliases actually exists, we use that.  */
                for (a = aliases + 1; *a && !found; a++) {
                  string atry = concat (*db_dirs, *a);
                  if (kpathsea_readable_file (kpse, atry))
                    found = atry;
                  else
                    free (atry);
                }
              }

              /* If we have a real file, add it to the list, maybe done.  */
              if (found) {
                str_list_add (ret, found);
                if (!all && found)
                  done = true;
              }
            } else { /* no match in the db */
              free (db_file);
            }

            /* On to the next directory, if any.  */
            db_dirs++;
          }

          /* This is just the space for the pointers, not the strings.  */
          if (orig_dirs && *orig_dirs)
              free (orig_dirs);
      }

      free ((void *) aliases);
      if (temp_str)
          free (temp_str);
  }

  return ret;
}
예제 #19
0
파일: db.c 프로젝트: starseeker/ModTeX
static boolean
db_build (kpathsea kpse, hash_table_type *table,  const_string db_filename)
{
  string line;
  unsigned dir_count = 0, file_count = 0, ignore_dir_count = 0;
  unsigned len = strlen (db_filename) - sizeof (DB_NAME) + 1; /* Keep the /. */
  string top_dir = (string)xmalloc (len + 1);
  string cur_dir = NULL; /* First thing in ls-R might be a filename.  */
  FILE *db_file = fopen (db_filename, FOPEN_R_MODE);
#if defined(WIN32)
  string pp;
#endif

  strncpy (top_dir, db_filename, len);
  top_dir[len] = 0;

  if (db_file) {
    while ((line = read_line (db_file)) != NULL) {
      len = strlen (line);

#if defined(WIN32)
      for (pp = line; *pp; pp++) {
        if (IS_KANJI(pp))
          pp++;
        else
          *pp = TRANSFORM(*pp);
      }
#endif

      /* A line like `/foo:' = new dir foo.  Allow both absolute (/...)
         and explicitly relative (./...) names here.  It's a kludge to
         pass in the directory name with the trailing : still attached,
         but it doesn't actually hurt.  */
      if (len > 0 && line[len - 1] == ':'
          && kpathsea_absolute_p (kpse, line, true)) {
        /* New directory line.  */
        if (!ignore_dir_p (line)) {
          /* If they gave a relative name, prepend full directory name now.  */
          line[len - 1] = DIR_SEP;
          /* Skip over leading `./', it confuses `match' and is just a
             waste of space, anyway.  This will lose on `../', but `match'
             won't work there, either, so it doesn't matter.  */
          cur_dir = *line == '.' ? concat (top_dir, line + 2) : xstrdup (line);
          dir_count++;
        } else {
          cur_dir = NULL;
          ignore_dir_count++;
        }

      /* Ignore blank, `.' and `..' lines.  */
      } else if (*line != 0 && cur_dir   /* a file line? */
                 && !(*line == '.'
                      && (line[1] == 0 || (line[1] == '.' && line[2] == 0))))
      {
        /* Make a new hash table entry with a key of `line' and a data
           of `cur_dir'.  An already-existing identical key is ok, since
           a file named `foo' can be in more than one directory.  Share
           `cur_dir' among all its files (and hence never free it).

           Note that we assume that all names in the ls-R file have already
           been case-smashed to lowercase where appropriate.
        */
        hash_insert_normalized (table, xstrdup (line), cur_dir);
        file_count++;

      } /* else ignore blank lines or top-level files
           or files in ignored directories*/

      free (line);
    }

    xfclose (db_file, db_filename);

    if (file_count == 0) {
      WARNING1 ("kpathsea: %s: No usable entries in ls-R", db_filename);
      WARNING ("kpathsea: See the manual for how to generate ls-R");
      db_file = NULL;
    } else {
      str_list_add (&(kpse->db_dir_list), xstrdup (top_dir));
    }

#ifdef KPSE_DEBUG
    if (KPATHSEA_DEBUG_P (KPSE_DEBUG_HASH)) {
      /* Don't make this a debugging bit, since the output is so
         voluminous, and being able to specify -1 is too useful.
         Instead, let people who want it run the program under
         a debugger and change the variable that way.  */
      boolean hash_summary_only = true;

      DEBUGF4 ("%s: %u entries in %d directories (%d hidden).\n",
               db_filename, file_count, dir_count, ignore_dir_count);
      DEBUGF ("ls-R hash table:");
      hash_print (*table, hash_summary_only);
      fflush (stderr);
    }
#endif /* KPSE_DEBUG */
  }

  free (top_dir);

  return db_file != NULL;
}
예제 #20
0
int vgcreate(struct cmd_context *cmd, int argc, char **argv)
{
	struct vgcreate_params vp_new;
	struct vgcreate_params vp_def;
	struct volume_group *vg;
	const char *tag;
	const char *clustered_message = "";
	char *vg_name;
	struct pvcreate_params pp;

	if (!argc) {
		log_error("Please provide volume group name and "
			  "physical volumes");
		return EINVALID_CMD_LINE;
	}

	vg_name = argv[0];
	argc--;
	argv++;

	if (arg_count(cmd, metadatacopies_ARG)) {
		log_error("Invalid option --metadatacopies, "
			  "use --pvmetadatacopies instead.");
		return EINVALID_CMD_LINE;
	}
	pvcreate_params_set_defaults(&pp);
	if (!pvcreate_params_validate(cmd, argc, argv, &pp)) {
		return EINVALID_CMD_LINE;
	}

	vgcreate_params_set_defaults(&vp_def, NULL);
	vp_def.vg_name = vg_name;
	if (vgcreate_params_set_from_args(cmd, &vp_new, &vp_def))
		return EINVALID_CMD_LINE;

	if (vgcreate_params_validate(cmd, &vp_new))
	    return EINVALID_CMD_LINE;

	/* Create the new VG */
	vg = vg_create(cmd, vp_new.vg_name);
	if (vg_read_error(vg))
		goto_bad;

	if (!vg_set_extent_size(vg, vp_new.extent_size) ||
	    !vg_set_max_lv(vg, vp_new.max_lv) ||
	    !vg_set_max_pv(vg, vp_new.max_pv) ||
	    !vg_set_alloc_policy(vg, vp_new.alloc) ||
	    !vg_set_clustered(vg, vp_new.clustered))
		goto_bad;

	if (!lock_vol(cmd, VG_ORPHANS, LCK_VG_WRITE)) {
		log_error("Can't get lock for orphan PVs");
		goto bad_orphan;
	}

	/* attach the pv's */
	if (!vg_extend(vg, argc, argv, &pp))
		goto_bad;

	if (vp_new.max_lv != vg->max_lv)
		log_warn("WARNING: Setting maxlogicalvolumes to %d "
			 "(0 means unlimited)", vg->max_lv);

	if (vp_new.max_pv != vg->max_pv)
		log_warn("WARNING: Setting maxphysicalvolumes to %d "
			 "(0 means unlimited)", vg->max_pv);

	if (arg_count(cmd, addtag_ARG)) {
		if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
			log_error("Failed to get tag");
			goto bad;
		}

		if (!(vg->fid->fmt->features & FMT_TAGS)) {
			log_error("Volume group format does not support tags");
			goto bad;
		}

		if (!str_list_add(cmd->mem, &vg->tags, tag)) {
			log_error("Failed to add tag %s to volume group %s",
				  tag, vp_new.vg_name);
			goto bad;
		}
	}

	if (vg_is_clustered(vg)) {
		clustered_message = "Clustered ";
	} else {
		if (locking_is_clustered())
			clustered_message = "Non-clustered ";
	}

	if (!archive(vg))
		goto_bad;

	/* Store VG on disk(s) */
	if (!vg_write(vg) || !vg_commit(vg))
		goto_bad;

	unlock_vg(cmd, VG_ORPHANS);
	unlock_vg(cmd, vp_new.vg_name);

	backup(vg);

	log_print("%s%colume group \"%s\" successfully created",
		  clustered_message, *clustered_message ? 'v' : 'V', vg->name);

	vg_release(vg);
	return ECMD_PROCESSED;

bad:
	unlock_vg(cmd, VG_ORPHANS);
bad_orphan:
	vg_release(vg);
	unlock_vg(cmd, vp_new.vg_name);
	return ECMD_FAILED;
}
예제 #21
0
/*
  run a command as a child process, with a timeout.

  any stdout/stderr from the child will appear in the Samba logs with
  the specified log levels
 */
struct tevent_req *samba_runcmd_send(TALLOC_CTX *mem_ctx,
				     struct tevent_context *ev,
				     struct timeval endtime,
				     int stdout_log_level,
				     int stderr_log_level,
				     const char * const *argv0, ...)
{
	struct tevent_req *req;
	struct samba_runcmd_state *state;
	int p1[2], p2[2], p3[2];
	char **argv;
	va_list ap;

	if (argv0 == NULL) {
		return NULL;
	}

	req = tevent_req_create(mem_ctx, &state,
				struct samba_runcmd_state);
	if (req == NULL) {
		return NULL;
	}

	state->stdout_log_level = stdout_log_level;
	state->stderr_log_level = stderr_log_level;
	state->fd_stdin = -1;

	state->arg0 = talloc_strdup(state, argv0[0]);
	if (tevent_req_nomem(state->arg0, req)) {
		return tevent_req_post(req, ev);
	}

	if (pipe(p1) != 0) {
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}
	if (pipe(p2) != 0) {
		close(p1[0]);
		close(p1[1]);
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}
	if (pipe(p3) != 0) {
		close(p1[0]);
		close(p1[1]);
		close(p2[0]);
		close(p2[1]);
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}

	state->tfork = tfork_create();
	if (state->tfork == NULL) {
		close(p1[0]);
		close(p1[1]);
		close(p2[0]);
		close(p2[1]);
		close(p3[0]);
		close(p3[1]);
		tevent_req_error(req, errno);
		return tevent_req_post(req, ev);
	}
	state->pid = tfork_child_pid(state->tfork);
	if (state->pid != 0) {
		/* the parent */
		close(p1[1]);
		close(p2[1]);
		close(p3[0]);
		state->fd_stdout = p1[0];
		state->fd_stderr = p2[0];
		state->fd_stdin  = p3[1];
		state->fd_status = tfork_event_fd(state->tfork);

		set_blocking(state->fd_stdout, false);
		set_blocking(state->fd_stderr, false);
		set_blocking(state->fd_stdin,  false);
		set_blocking(state->fd_status, false);

		smb_set_close_on_exec(state->fd_stdin);
		smb_set_close_on_exec(state->fd_stdout);
		smb_set_close_on_exec(state->fd_stderr);
		smb_set_close_on_exec(state->fd_status);

		tevent_req_set_cleanup_fn(req, samba_runcmd_cleanup_fn);

		state->fde_stdout = tevent_add_fd(ev, state,
						  state->fd_stdout,
						  TEVENT_FD_READ,
						  samba_runcmd_io_handler,
						  req);
		if (tevent_req_nomem(state->fde_stdout, req)) {
			close(state->fd_stdout);
			close(state->fd_stderr);
			close(state->fd_status);
			return tevent_req_post(req, ev);
		}
		tevent_fd_set_auto_close(state->fde_stdout);

		state->fde_stderr = tevent_add_fd(ev, state,
						  state->fd_stderr,
						  TEVENT_FD_READ,
						  samba_runcmd_io_handler,
						  req);
		if (tevent_req_nomem(state->fde_stdout, req)) {
			close(state->fd_stdout);
			close(state->fd_stderr);
			close(state->fd_status);
			return tevent_req_post(req, ev);
		}
		tevent_fd_set_auto_close(state->fde_stderr);

		state->fde_status = tevent_add_fd(ev, state,
						  state->fd_status,
						  TEVENT_FD_READ,
						  samba_runcmd_io_handler,
						  req);
		if (tevent_req_nomem(state->fde_stdout, req)) {
			close(state->fd_stdout);
			close(state->fd_stderr);
			close(state->fd_status);
			return tevent_req_post(req, ev);
		}
		tevent_fd_set_auto_close(state->fde_status);

		if (!timeval_is_zero(&endtime)) {
			tevent_req_set_endtime(req, ev, endtime);
		}

		return req;
	}

	/* the child */
	close(p1[0]);
	close(p2[0]);
	close(p3[1]);
	close(0);
	close(1);
	close(2);

	/* we want to ensure that all of the network sockets we had
	   open are closed */
	tevent_re_initialise(ev);

	/* setup for logging to go to the parents debug log */
	dup2(p3[0], 0);
	dup2(p1[1], 1);
	dup2(p2[1], 2);

	close(p1[1]);
	close(p2[1]);
	close(p3[0]);

	argv = str_list_copy(state, discard_const_p(const char *, argv0));
	if (!argv) {
		fprintf(stderr, "Out of memory in child\n");
		_exit(255);
	}

	va_start(ap, argv0);
	while (1) {
		const char **l;
		char *arg = va_arg(ap, char *);
		if (arg == NULL) break;
		l = discard_const_p(const char *, argv);
		l = str_list_add(l, arg);
		if (l == NULL) {
			fprintf(stderr, "Out of memory in child\n");
			_exit(255);
		}
		argv = discard_const_p(char *, l);
	}
	va_end(ap);

	(void)execvp(state->arg0, argv);
	fprintf(stderr, "Failed to exec child - %s\n", strerror(errno));
	_exit(255);
	return NULL;
}
예제 #22
0
search P4C(const_string, path,  const_string, original_name,
           boolean, must_exist,  boolean, all)
{
  str_list_type ret_list;
  string name;
  boolean absolute_p;

#ifdef __DJGPP__
  /* We will use `stat' heavily, so let's request for
     the fastest possible version of `stat', by telling
     it what members of struct stat do we really need.

     We need to set this on each call because this is a
     library function; the caller might need other options
     from `stat'.  Thus save the flags and restore them
     before exit.

     This call tells `stat' that we do NOT need to recognize
     executable files (neither by an extension nor by a magic
     signature); that we do NOT need time stamp of root directories;
     and that we do NOT need the write access bit in st_mode.

     Note that `kpse_set_progname' needs the EXEC bits,
     but it was already called by the time we get here.  */
  unsigned short save_djgpp_flags  = _djstat_flags;

  _djstat_flags = _STAT_EXEC_MAGIC | _STAT_EXEC_EXT
		  | _STAT_ROOT_TIME | _STAT_WRITEBIT;
#endif

  /* Make a leading ~ count as an absolute filename, and expand $FOO's.  */
  name = kpse_expand (original_name);
  
  /* If the first name is absolute or explicitly relative, no need to
     consider PATH at all.  */
  absolute_p = kpse_absolute_p (name, true);
  
  if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
    DEBUGF4 ("start search(file=%s, must_exist=%d, find_all=%d, path=%s).\n",
             name, must_exist, all, path);

  /* Find the file(s). */
  ret_list = absolute_p ? absolute_search (name)
                        : path_search (path, name, must_exist, all);
  
  /* Append NULL terminator if we didn't find anything at all, or we're
     supposed to find ALL and the list doesn't end in NULL now.  */
  if (STR_LIST_LENGTH (ret_list) == 0
      || (all && STR_LIST_LAST_ELT (ret_list) != NULL))
    str_list_add (&ret_list, NULL);

  /* The very first search is for texmf.cnf.  We can't log that, since
     we want to allow setting TEXMFLOG in texmf.cnf.  */
  if (first_search) {
    first_search = false;
  } else {
    /* Record the filenames we found, if desired.  And wrap them in a
       debugging line if we're doing that.  */
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
      DEBUGF1 ("search(%s) =>", original_name);
    log_search (ret_list);
    if (KPSE_DEBUG_P (KPSE_DEBUG_SEARCH))
      putc ('\n', stderr);
  }  

#ifdef __DJGPP__
  /* Undo any side effects.  */
  _djstat_flags = save_djgpp_flags;
#endif

  return STR_LIST (ret_list);
}
예제 #23
0
static str_list_type
path_search P4C(const_string, path,  string, name,
                boolean, must_exist,  boolean, all)
{
  string elt;
  str_list_type ret_list;
  boolean done = false;
  ret_list = str_list_init (); /* some compilers lack struct initialization */

  for (elt = kpse_path_element (path); !done && elt;
       elt = kpse_path_element (NULL)) {
    str_list_type *found;
    boolean allow_disk_search = true;

    if (*elt == '!' && *(elt + 1) == '!') {
      /* Those magic leading chars in a path element means don't search the
         disk for this elt.  And move past the magic to get to the name.  */
      allow_disk_search = false;
      elt += 2;
    }

    /* See elt-dirs.c for side effects of this function */
    kpse_normalize_path(elt);
    
    /* Try ls-R, unless we're searching for texmf.cnf.  Our caller
       (search), also tests first_search, and does the resetting.  */
    found = first_search ? NULL : kpse_db_search (name, elt, all);

    /* Search the filesystem if (1) the path spec allows it, and either
         (2a) we are searching for texmf.cnf ; or
         (2b) no db exists; or 
         (2c) no db's are relevant to this elt; or
         (3) MUST_EXIST && NAME was not in the db.
       In (2*), `found' will be NULL.
       In (3),  `found' will be an empty list. */
    if (allow_disk_search && (!found || (must_exist && !STR_LIST (*found)))) {
      str_llist_type *dirs = kpse_element_dirs (elt);
      if (dirs && *dirs) {
        if (!found)
          found = XTALLOC1 (str_list_type);
        *found = dir_list_search (dirs, name, all);
      }
    }
    
    /* Did we find anything anywhere?  */
    if (found && STR_LIST (*found))
      if (all)
        str_list_concat (&ret_list, *found);
      else {
        str_list_add (&ret_list, STR_LIST_ELT (*found, 0));
        done = true;
      }

    /* Free the list space, if any (but not the elements).  */
    if (found) {
      str_list_free (found);
      free (found);
    }
  }

  /* Free the expanded name we were passed.  It can't be in the return
     list, since the path directories got unconditionally prepended.  */
  free (name);
  
  return ret_list;
}      
예제 #24
0
/*
  query a name
*/
static void nbtd_winsserver_query(struct loadparm_context *lp_ctx,
				  struct nbt_name_socket *nbtsock, 
				  struct nbt_name_packet *packet, 
				  struct socket_address *src)
{
	NTSTATUS status;
	struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data,
						       struct nbtd_interface);
	struct wins_server *winssrv = iface->nbtsrv->winssrv;
	struct nbt_name *name = &packet->questions[0].name;
	struct winsdb_record *rec;
	struct winsdb_record *rec_1b = NULL;
	const char **addresses;
	const char **addresses_1b = NULL;
	uint16_t nb_flags = 0;

	if (name->type == NBT_NAME_MASTER) {
		goto notfound;
	}

	/*
	 * w2k3 returns the first address of the 0x1B record as first address
	 * to a 0x1C query
	 *
	 * since Windows 2000 Service Pack 2 there's on option to trigger this behavior:
	 *
	 * HKEY_LOCAL_MACHINE\System\CurrentControlset\Services\WINS\Parameters\Prepend1BTo1CQueries
	 * Typ: Daten REG_DWORD
	 * Value: 0 = deactivated, 1 = activated
	 */
	if (name->type == NBT_NAME_LOGON && 
	    lpcfg_parm_bool(lp_ctx, NULL, "nbtd", "wins_prepend1Bto1Cqueries", true)) {
		struct nbt_name name_1b;

		name_1b = *name;
		name_1b.type = NBT_NAME_PDC;

		status = winsdb_lookup(winssrv->wins_db, &name_1b, packet, &rec_1b);
		if (NT_STATUS_IS_OK(status)) {
			addresses_1b = winsdb_addr_string_list(packet, rec_1b->addresses);
		}
	}

	status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
	if (!NT_STATUS_IS_OK(status)) {
		if (!lpcfg_wins_dns_proxy(lp_ctx)) {
			goto notfound;
		}

		if (name->type != NBT_NAME_CLIENT && name->type != NBT_NAME_SERVER) {
			goto notfound;
		}

		nbtd_wins_dns_proxy_query(nbtsock, packet, src);
		return;
	}

	/*
	 * for group's we always reply with
	 * 255.255.255.255 as address, even if
	 * the record is released or tombstoned
	 */
	if (rec->type == WREPL_TYPE_GROUP) {
		addresses = str_list_add(NULL, "255.255.255.255");
		talloc_steal(packet, addresses);
		if (!addresses) {
			goto notfound;
		}
		nb_flags |= NBT_NM_GROUP;
		goto found;
	}

	if (rec->state != WREPL_STATE_ACTIVE) {
		goto notfound;
	}

	addresses = winsdb_addr_string_list(packet, rec->addresses);
	if (!addresses) {
		goto notfound;
	}

	/* 
	 * if addresses_1b isn't NULL, we have a 0x1C query and need to return the
	 * first 0x1B address as first address
	 */
	if (addresses_1b && addresses_1b[0]) {
		const char **addresses_1c = addresses;
		uint32_t i;
		uint32_t num_addrs;

		addresses = str_list_add(NULL, addresses_1b[0]);
		if (!addresses) {
			goto notfound;
		}
		talloc_steal(packet, addresses);
		num_addrs = 1;

		for (i=0; addresses_1c[i]; i++) {
			if (strcmp(addresses_1b[0], addresses_1c[i]) == 0) continue;

			/*
			 * stop when we already have 25 addresses
			 */
			if (num_addrs >= 25) break;

			num_addrs++;			
			addresses = str_list_add(addresses, addresses_1c[i]);
			if (!addresses) {
				goto notfound;
			}
		}
	}

	if (rec->type == WREPL_TYPE_SGROUP) {
		nb_flags |= NBT_NM_GROUP;
	} else {
		nb_flags |= (rec->node <<13);
	}

	/*
	 * since Windows 2000 Service Pack 2 there's on option to trigger this behavior:
	 *
	 * HKEY_LOCAL_MACHINE\System\CurrentControlset\Services\WINS\Parameters\Randomize1CList
	 * Typ: Daten REG_DWORD
	 * Value: 0 = deactivated, 1 = activated
	 */
	if (name->type == NBT_NAME_LOGON && 
	    lpcfg_parm_bool(lp_ctx, NULL, "nbtd", "wins_randomize1Clist", false)) {
		nbtd_wins_randomize1Clist(lp_ctx, addresses, src);
	}

found:
	nbtd_name_query_reply(nbtsock, packet, src, name, 
			      0, nb_flags, addresses);
	return;

notfound:
	nbtd_negative_name_query_reply(nbtsock, packet, src);
}
예제 #25
0
int vgcreate(struct cmd_context *cmd, int argc, char **argv)
{
    size_t max_lv, max_pv;
    uint32_t extent_size;
    char *vg_name;
    struct volume_group *vg;
    const char *tag;
    alloc_policy_t alloc;
    int clustered;

    if (!argc) {
        log_error("Please provide volume group name and "
                  "physical volumes");
        return EINVALID_CMD_LINE;
    }

    if (argc == 1) {
        log_error("Please enter physical volume name(s)");
        return EINVALID_CMD_LINE;
    }

    vg_name = skip_dev_dir(cmd, argv[0], NULL);
    max_lv = arg_uint_value(cmd, maxlogicalvolumes_ARG, 0);
    max_pv = arg_uint_value(cmd, maxphysicalvolumes_ARG, 0);
    alloc = arg_uint_value(cmd, alloc_ARG, ALLOC_NORMAL);

    if (alloc == ALLOC_INHERIT) {
        log_error("Volume Group allocation policy cannot inherit "
                  "from anything");
        return EINVALID_CMD_LINE;
    }

    if (!(cmd->fmt->features & FMT_UNLIMITED_VOLS)) {
        if (!max_lv)
            max_lv = 255;
        if (!max_pv)
            max_pv = 255;
        if (max_lv > 255 || max_pv > 255) {
            log_error("Number of volumes may not exceed 255");
            return EINVALID_CMD_LINE;
        }
    }

    if (arg_sign_value(cmd, physicalextentsize_ARG, 0) == SIGN_MINUS) {
        log_error("Physical extent size may not be negative");
        return EINVALID_CMD_LINE;
    }

    if (arg_sign_value(cmd, maxlogicalvolumes_ARG, 0) == SIGN_MINUS) {
        log_error("Max Logical Volumes may not be negative");
        return EINVALID_CMD_LINE;
    }

    if (arg_sign_value(cmd, maxphysicalvolumes_ARG, 0) == SIGN_MINUS) {
        log_error("Max Physical Volumes may not be negative");
        return EINVALID_CMD_LINE;
    }

    /* Units of 512-byte sectors */
    extent_size =
        arg_uint_value(cmd, physicalextentsize_ARG, DEFAULT_EXTENT) * 2;

    if (!extent_size) {
        log_error("Physical extent size may not be zero");
        return EINVALID_CMD_LINE;
    }

    if (!validate_vg_name(cmd, vg_name)) {
        log_error("New volume group name \"%s\" is invalid", vg_name);
        return ECMD_FAILED;
    }

    /* Create the new VG */
    if (!(vg = vg_create(cmd, vg_name, extent_size, max_pv, max_lv, alloc,
                         argc - 1, argv + 1)))
        return ECMD_FAILED;

    if (max_lv != vg->max_lv)
        log_warn("WARNING: Setting maxlogicalvolumes to %d "
                 "(0 means unlimited)", vg->max_lv);

    if (max_pv != vg->max_pv)
        log_warn("WARNING: Setting maxphysicalvolumes to %d "
                 "(0 means unlimited)", vg->max_pv);

    if (arg_count(cmd, addtag_ARG)) {
        if (!(tag = arg_str_value(cmd, addtag_ARG, NULL))) {
            log_error("Failed to get tag");
            return ECMD_FAILED;
        }

        if (!(vg->fid->fmt->features & FMT_TAGS)) {
            log_error("Volume group format does not support tags");
            return ECMD_FAILED;
        }

        if (!str_list_add(cmd->mem, &vg->tags, tag)) {
            log_error("Failed to add tag %s to volume group %s",
                      tag, vg_name);
            return ECMD_FAILED;
        }
    }

    if (arg_count(cmd, clustered_ARG))
        clustered = !strcmp(arg_str_value(cmd, clustered_ARG, "n"), "y");
    else
        /* Default depends on current locking type */
        clustered = locking_is_clustered();

    if (clustered)
        vg->status |= CLUSTERED;
    else
        vg->status &= ~CLUSTERED;

    if (!lock_vol(cmd, ORPHAN, LCK_VG_WRITE)) {
        log_error("Can't get lock for orphan PVs");
        return ECMD_FAILED;
    }

    if (!lock_vol(cmd, vg_name, LCK_VG_WRITE | LCK_NONBLOCK)) {
        log_error("Can't get lock for %s", vg_name);
        unlock_vg(cmd, ORPHAN);
        return ECMD_FAILED;
    }

    if (!archive(vg)) {
        unlock_vg(cmd, vg_name);
        unlock_vg(cmd, ORPHAN);
        return ECMD_FAILED;
    }

    /* Store VG on disk(s) */
    if (!vg_write(vg) || !vg_commit(vg)) {
        unlock_vg(cmd, vg_name);
        unlock_vg(cmd, ORPHAN);
        return ECMD_FAILED;
    }

    unlock_vg(cmd, vg_name);
    unlock_vg(cmd, ORPHAN);

    backup(vg);

    log_print("Volume group \"%s\" successfully created", vg->name);

    return ECMD_PROCESSED;
}