/* Adds a new column to 'table' just to the right of any existing column, with * 'heading' as a title for the column. 'heading' must be a valid printf() * format specifier. * * Columns must be added before any data is put into 'table'. */ void table_add_column(struct table *table, const char *heading, ...) { struct column *column; va_list args; assert(!table->n_rows); if (table->n_columns >= table->allocated_columns) { table->columns = x2nrealloc(table->columns, &table->allocated_columns, sizeof *table->columns); } column = &table->columns[table->n_columns++]; va_start(args, heading); column->heading = xvasprintf(heading, args); va_end(args); }
void add_exclude (struct exclude *ex, char const *pattern, int options) { struct exclude_segment *seg; if ((options & EXCLUDE_WILDCARDS) && fnmatch_pattern_has_wildcards (pattern, options)) { struct exclude_pattern *pat; struct patopts *patopts; if (ex->tail && ex->tail->type == exclude_pattern && ((ex->tail->options & EXCLUDE_INCLUDE) == (options & EXCLUDE_INCLUDE))) seg = ex->tail; else seg = new_exclude_segment (ex, exclude_pattern, options); pat = &seg->v.pat; if (pat->exclude_count == pat->exclude_alloc) pat->exclude = x2nrealloc (pat->exclude, &pat->exclude_alloc, sizeof *pat->exclude); patopts = &pat->exclude[pat->exclude_count++]; patopts->pattern = pattern; patopts->options = options; } else { char *str, *p; #define EXCLUDE_HASH_FLAGS (EXCLUDE_INCLUDE|EXCLUDE_ANCHORED|\ FNM_LEADING_DIR|FNM_CASEFOLD) if (ex->tail && ex->tail->type == exclude_hash && ((ex->tail->options & EXCLUDE_HASH_FLAGS) == (options & EXCLUDE_HASH_FLAGS))) seg = ex->tail; else seg = new_exclude_segment (ex, exclude_hash, options); str = xstrdup (pattern); if (options & EXCLUDE_WILDCARDS) unescape_pattern (str); p = hash_insert (seg->v.table, str); if (p != str) free (str); } }
/* Registers 'file' to be unlinked when the program terminates via exit() or a * fatal signal. */ void fatal_signal_add_file_to_unlink(const char *file) { static bool added_hook = false; if (!added_hook) { added_hook = true; fatal_signal_add_hook(unlink_files, NULL, true); fatal_signal_add_hook(destroy_pipeline, NULL, true); } fatal_signal_block(); if (n_files >= max_files) { files = x2nrealloc(files, &max_files, sizeof *files); } files[n_files++] = xstrdup(file); fatal_signal_unblock(); }
static size_t readname (char **name, size_t *size, FILE *stream) { int c; size_t name_index = 0; /* Skip blank space. */ while ((c = getc (stream)) != EOF && isspace (c)) /* Do nothing. */ ; for (;;) { if (*size <= name_index) *name = x2nrealloc (*name, size, sizeof **name); if (c == EOF || isspace (c)) break; (*name)[name_index++] = c; c = getc (stream); } (*name)[name_index] = '\0'; return name_index; }
int read_utmp (char const *file, size_t *n_entries, STRUCT_UTMP **utmp_buf, int options) { size_t n_read = 0; size_t n_alloc = 0; STRUCT_UTMP *utmp = NULL; int saved_errno; FILE *f = fopen (file, "r"); if (! f) return -1; for (;;) { if (n_read == n_alloc) utmp = x2nrealloc (utmp, &n_alloc, sizeof *utmp); if (fread (&utmp[n_read], sizeof utmp[n_read], 1, f) == 0) break; n_read += desirable_utmp_entry (&utmp[n_read], options); } saved_errno = ferror (f) ? errno : 0; if (fclose (f) != 0) saved_errno = errno; if (saved_errno != 0) { free (utmp); errno = saved_errno; return -1; } *n_entries = n_read; *utmp_buf = utmp; return 0; }
/* DIR is the operand of a -C option; add it to vector of chdir targets, and return the index of its location. */ int chdir_arg (char const *dir) { if (wd_count == wd_alloc) { if (wd_alloc == 0) { wd_alloc = 2; wd = xmalloc (sizeof *wd * wd_alloc); } else wd = x2nrealloc (wd, &wd_alloc, sizeof *wd); if (! wd_count) { wd[wd_count].name = "."; wd[wd_count].fd = AT_FDCWD; wd_count++; } } /* Optimize the common special case of the working directory, or the working directory as a prefix. */ if (dir[0]) { while (dir[0] == '.' && ISSLASH (dir[1])) for (dir += 2; ISSLASH (*dir); dir++) continue; if (! dir[dir[0] == '.']) return wd_count - 1; } wd[wd_count].name = dir; wd[wd_count].fd = 0; return wd_count++; }
char * streamsavedir (DIR *dirp, enum savedir_option option) { char *name_space = NULL; size_t allocated = 0; direntry_t *entries = NULL; size_t entries_allocated = 0; size_t entries_used = 0; size_t used = 0; int readdir_errno; comparison_function cmp = comparison_function_table[option]; if (dirp == NULL) return NULL; for (;;) { struct dirent const *dp; char const *entry; errno = 0; dp = readdir (dirp); if (! dp) break; /* Skip "", ".", and "..". "" is returned by at least one buggy implementation: Solaris 2.4 readdir on NFS file systems. */ entry = dp->d_name; if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') { size_t entry_size = _D_EXACT_NAMLEN (dp) + 1; if (cmp) { if (entries_allocated == entries_used) { size_t n = entries_allocated; entries = x2nrealloc (entries, &n, sizeof *entries); entries_allocated = n; } entries[entries_used].name = xstrdup (entry); #if D_INO_IN_DIRENT entries[entries_used].ino = dp->d_ino; #endif entries_used++; } else { if (allocated - used <= entry_size) { size_t n = used + entry_size; if (n < used) xalloc_die (); name_space = x2nrealloc (name_space, &n, 1); allocated = n; } memcpy (name_space + used, entry, entry_size); } used += entry_size; } } readdir_errno = errno; if (readdir_errno != 0) { free (entries); free (name_space); errno = readdir_errno; return NULL; } if (cmp) { size_t i; qsort (entries, entries_used, sizeof *entries, cmp); name_space = xmalloc (used + 1); used = 0; for (i = 0; i < entries_used; i++) { char *dest = name_space + used; used += stpcpy (dest, entries[i].name) - dest + 1; free (entries[i].name); } free (entries); } else if (used == allocated) name_space = xrealloc (name_space, used + 1); name_space[used] = '\0'; return name_space; }
void *x2realloc( void *p, size_t *pn ) { return x2nrealloc( p, pn, ebp_16 ); }
static char* do_time_format (const char *fmt, const struct tm *p, const char *ns, size_t ns_size) { static char *buf = NULL; static size_t buf_size; char *timefmt = NULL; struct tm altered_time; /* If the format expands to nothing (%p in some locales, for * example), strftime can return 0. We actually want to distinguish * the error case where the buffer is too short, so we just prepend * an otherwise uninteresting character to prevent the no-output * case. */ timefmt = xmalloc (strlen (fmt) + 2u); timefmt[0] = '_'; memcpy (timefmt + 1, fmt, strlen (fmt) + 1); /* altered_time is a similar time, but in which both * digits of the seconds field are different. */ altered_time = *p; if (altered_time.tm_sec >= 11) altered_time.tm_sec -= 11; else altered_time.tm_sec += 11; /* If we call strftime() with buf_size=0, the program will coredump * on Solaris, since it unconditionally writes the terminating null * character. */ if (buf == NULL) { buf_size = 1u; buf = xmalloc (buf_size); } while (true) { /* I'm not sure that Solaris will return 0 when the buffer is too small. * Therefore we do not check for (buf_used != 0) as the termination * condition. */ size_t buf_used = strftime (buf, buf_size, timefmt, p); if (buf_used /* Conforming POSIX system */ && (buf_used < buf_size)) /* Solaris workaround */ { char *altbuf; size_t i = 0, n = 0; size_t final_len = (buf_used + 1u /* for \0 */ + ns_size); buf = xrealloc (buf, final_len); buf_size = final_len; altbuf = xmalloc (final_len); strftime (altbuf, buf_size, timefmt, &altered_time); /* Find the seconds digits; they should be the only changed part. * In theory the result of the two formatting operations could differ in * more than just one sequence of decimal digits (for example %X might * in theory return a spelled-out time like "thirty seconds past noon"). * When that happens, we just avoid inserting the nanoseconds field. */ if (scan_for_digit_differences (buf, altbuf, &i, &n) && (2==n) && !isdigit ((unsigned char)buf[i+n])) { const size_t end_of_seconds = i + n; const size_t suffix_len = buf_used-(end_of_seconds)+1; /* Move the tail (including the \0). Note that this * is a move of an overlapping memory block, so we * must use memmove instead of memcpy. Then insert * the nanoseconds (but not its trailing \0). */ assert (end_of_seconds + ns_size + suffix_len == final_len); memmove (buf+end_of_seconds+ns_size, buf+end_of_seconds, suffix_len); memcpy (buf+i+n, ns, ns_size); } else { /* No seconds digits. No need to insert anything. */ } /* The first character of buf is the underscore, which we actually * don't want. */ free (timefmt); free (altbuf); return buf+1; } else { buf = x2nrealloc (buf, &buf_size, sizeof *buf); } } }
static void do_listen(struct ovs_cmdl_context *ctx) { struct pstream *pstream; struct jsonrpc **rpcs; size_t n_rpcs, allocated_rpcs; bool done; int error; error = jsonrpc_pstream_open(ctx->argv[1], &pstream, DSCP_DEFAULT); if (error) { ovs_fatal(error, "could not listen on \"%s\"", ctx->argv[1]); } daemonize(); rpcs = NULL; n_rpcs = allocated_rpcs = 0; done = false; for (;;) { struct stream *stream; size_t i; /* Accept new connections. */ error = pstream_accept(pstream, &stream); if (!error) { if (n_rpcs >= allocated_rpcs) { rpcs = x2nrealloc(rpcs, &allocated_rpcs, sizeof *rpcs); } rpcs[n_rpcs++] = jsonrpc_open(stream); } else if (error != EAGAIN) { ovs_fatal(error, "pstream_accept failed"); } /* Service existing connections. */ for (i = 0; i < n_rpcs; ) { struct jsonrpc *rpc = rpcs[i]; struct jsonrpc_msg *msg; jsonrpc_run(rpc); if (!jsonrpc_get_backlog(rpc)) { error = jsonrpc_recv(rpc, &msg); if (!error) { error = handle_rpc(rpc, msg, &done); jsonrpc_msg_destroy(msg); } else if (error == EAGAIN) { error = 0; } } if (!error) { error = jsonrpc_get_status(rpc); } if (error) { jsonrpc_close(rpc); ovs_error(error, "connection closed"); memmove(&rpcs[i], &rpcs[i + 1], (n_rpcs - i - 1) * sizeof *rpcs); n_rpcs--; } else { i++; } } /* Wait for something to do. */ if (done && !n_rpcs) { break; } pstream_wait(pstream); for (i = 0; i < n_rpcs; i++) { struct jsonrpc *rpc = rpcs[i]; jsonrpc_wait(rpc); if (!jsonrpc_get_backlog(rpc)) { jsonrpc_recv_wait(rpc); } } poll_block(); } free(rpcs); pstream_close(pstream); }
void add_exclude (struct exclude *ex, char const *pattern, int options) { struct exclude_segment *seg; struct exclude_pattern *pat; struct patopts *patopts; if ((options & (EXCLUDE_REGEX|EXCLUDE_WILDCARDS)) && fnmatch_pattern_has_wildcards (pattern, options)) { if (! (ex->head && ex->head->type == exclude_pattern && ((ex->head->options & EXCLUDE_INCLUDE) == (options & EXCLUDE_INCLUDE)))) new_exclude_segment (ex, exclude_pattern, options); seg = ex->head; pat = &seg->v.pat; if (pat->exclude_count == pat->exclude_alloc) pat->exclude = x2nrealloc (pat->exclude, &pat->exclude_alloc, sizeof *pat->exclude); patopts = &pat->exclude[pat->exclude_count++]; patopts->options = options; if (options & EXCLUDE_REGEX) { int rc; int cflags = REG_NOSUB|REG_EXTENDED| ((options & FNM_CASEFOLD) ? REG_ICASE : 0); if (options & FNM_LEADING_DIR) { char *tmp; size_t len = strlen (pattern); while (len > 0 && ISSLASH (pattern[len-1])) --len; if (len == 0) rc = 1; else { tmp = xmalloc (len + 7); memcpy (tmp, pattern, len); strcpy (tmp + len, "(/.*)?"); rc = regcomp (&patopts->v.re, tmp, cflags); free (tmp); } } else rc = regcomp (&patopts->v.re, pattern, cflags); if (rc) { pat->exclude_count--; return; } } else { if (options & EXCLUDE_ALLOC) { pattern = xstrdup (pattern); exclude_add_pattern_buffer (ex, (char*) pattern); } patopts->v.pattern = pattern; } } else { char *str, *p; int exclude_hash_flags = (EXCLUDE_INCLUDE | EXCLUDE_ANCHORED | FNM_LEADING_DIR | FNM_CASEFOLD); if (! (ex->head && ex->head->type == exclude_hash && ((ex->head->options & exclude_hash_flags) == (options & exclude_hash_flags)))) new_exclude_segment (ex, exclude_hash, options); seg = ex->head; str = xstrdup (pattern); if ((options & (EXCLUDE_WILDCARDS | FNM_NOESCAPE)) == EXCLUDE_WILDCARDS) unescape_pattern (str); p = hash_insert (seg->v.table, str); if (p != str) free (str); } }
size_t readtoken (FILE *stream, const char *delim, size_t n_delim, token_buffer *tokenbuffer) { char *p; int c; size_t i, n; static const char *saved_delim = NULL; static char isdelim[256]; bool same_delimiters; if (delim == NULL && saved_delim == NULL) abort (); same_delimiters = false; if (delim != saved_delim && saved_delim != NULL) { same_delimiters = true; for (i = 0; i < n_delim; i++) { if (delim[i] != saved_delim[i]) { same_delimiters = false; break; } } } if (!same_delimiters) { size_t j; saved_delim = delim; memset (isdelim, 0, sizeof isdelim); for (j = 0; j < n_delim; j++) { unsigned char ch = delim[j]; isdelim[ch] = 1; } } /* FIXME: don't fool with this caching. Use strchr instead. */ /* skip over any leading delimiters */ for (c = getc (stream); c >= 0 && isdelim[c]; c = getc (stream)) { /* empty */ } p = tokenbuffer->buffer; n = tokenbuffer->size; i = 0; for (;;) { if (c < 0 && i == 0) return -1; if (i == n) p = x2nrealloc (p, &n, sizeof *p); if (c < 0) { p[i] = 0; break; } if (isdelim[c]) { p[i] = 0; break; } p[i++] = c; c = getc (stream); } tokenbuffer->buffer = p; tokenbuffer->size = n; return i; }
static int combine_files (enum comb_command_type command, struct lexer *lexer, struct dataset *ds) { struct comb_proc proc; bool saw_by = false; bool saw_sort = false; struct casereader *active_file = NULL; char *first_name = NULL; char *last_name = NULL; struct taint *taint = NULL; size_t n_tables = 0; size_t allocated_files = 0; size_t i; proc.files = NULL; proc.n_files = 0; proc.dict = dict_create (get_default_encoding ()); proc.output = NULL; proc.matcher = NULL; subcase_init_empty (&proc.by_vars); proc.first = NULL; proc.last = NULL; proc.buffered_case = NULL; proc.prev_BY = NULL; dict_set_case_limit (proc.dict, dict_get_case_limit (dataset_dict (ds))); lex_match (lexer, T_SLASH); for (;;) { struct comb_file *file; enum comb_file_type type; if (lex_match_id (lexer, "FILE")) type = COMB_FILE; else if (command == COMB_MATCH && lex_match_id (lexer, "TABLE")) { type = COMB_TABLE; n_tables++; } else break; lex_match (lexer, T_EQUALS); if (proc.n_files >= allocated_files) proc.files = x2nrealloc (proc.files, &allocated_files, sizeof *proc.files); file = &proc.files[proc.n_files++]; file->type = type; subcase_init_empty (&file->by_vars); subcase_init_empty (&file->src); subcase_init_empty (&file->dst); file->mv = NULL; file->handle = NULL; file->dict = NULL; file->reader = NULL; file->data = NULL; file->is_sorted = true; file->in_name = NULL; file->in_var = NULL; if (lex_match (lexer, T_ASTERISK)) { if (!dataset_has_source (ds)) { msg (SE, _("Cannot specify the active dataset since none " "has been defined.")); goto error; } if (proc_make_temporary_transformations_permanent (ds)) msg (SE, _("This command may not be used after TEMPORARY when " "the active dataset is an input source. " "Temporary transformations will be made permanent.")); file->dict = dict_clone (dataset_dict (ds)); } else { file->handle = fh_parse (lexer, FH_REF_FILE, dataset_session (ds)); if (file->handle == NULL) goto error; file->reader = any_reader_open (file->handle, NULL, &file->dict); if (file->reader == NULL) goto error; } while (lex_match (lexer, T_SLASH)) if (lex_match_id (lexer, "RENAME")) { if (!parse_dict_rename (lexer, file->dict)) goto error; } else if (lex_match_id (lexer, "IN")) { lex_match (lexer, T_EQUALS); if (lex_token (lexer) != T_ID) { lex_error (lexer, NULL); goto error; } if (file->in_name) { msg (SE, _("Multiple IN subcommands for a single FILE or " "TABLE.")); goto error; } file->in_name = xstrdup (lex_tokcstr (lexer)); lex_get (lexer); } else if (lex_match_id (lexer, "SORT")) { file->is_sorted = false; saw_sort = true; } if (!merge_dictionary (proc.dict, file)) goto error; } while (lex_token (lexer) != T_ENDCMD) { if (lex_match (lexer, T_BY)) { const struct variable **by_vars; size_t i; bool ok; if (saw_by) { lex_sbc_only_once ("BY"); goto error; } saw_by = true; lex_match (lexer, T_EQUALS); if (!parse_sort_criteria (lexer, proc.dict, &proc.by_vars, &by_vars, NULL)) goto error; ok = true; for (i = 0; i < proc.n_files; i++) { struct comb_file *file = &proc.files[i]; size_t j; for (j = 0; j < subcase_get_n_fields (&proc.by_vars); j++) { const char *name = var_get_name (by_vars[j]); struct variable *var = dict_lookup_var (file->dict, name); if (var != NULL) subcase_add_var (&file->by_vars, var, subcase_get_direction (&proc.by_vars, j)); else { if (file->handle != NULL) msg (SE, _("File %s lacks BY variable %s."), fh_get_name (file->handle), name); else msg (SE, _("Active dataset lacks BY variable %s."), name); ok = false; } } assert (!ok || subcase_conformable (&file->by_vars, &proc.files[0].by_vars)); } free (by_vars); if (!ok) goto error; } else if (command != COMB_UPDATE && lex_match_id (lexer, "FIRST")) { if (first_name != NULL) { lex_sbc_only_once ("FIRST"); goto error; } lex_match (lexer, T_EQUALS); if (!lex_force_id (lexer)) goto error; first_name = xstrdup (lex_tokcstr (lexer)); lex_get (lexer); } else if (command != COMB_UPDATE && lex_match_id (lexer, "LAST")) { if (last_name != NULL) { lex_sbc_only_once ("LAST"); goto error; } lex_match (lexer, T_EQUALS); if (!lex_force_id (lexer)) goto error; last_name = xstrdup (lex_tokcstr (lexer)); lex_get (lexer); } else if (lex_match_id (lexer, "MAP")) { /* FIXME. */ } else if (lex_match_id (lexer, "DROP")) { if (!parse_dict_drop (lexer, proc.dict)) goto error; } else if (lex_match_id (lexer, "KEEP")) { if (!parse_dict_keep (lexer, proc.dict)) goto error; } else { lex_error (lexer, NULL); goto error; } if (!lex_match (lexer, T_SLASH) && lex_token (lexer) != T_ENDCMD) { lex_end_of_command (lexer); goto error; } } if (!saw_by) { if (command == COMB_UPDATE) { lex_sbc_missing ("BY"); goto error; } if (n_tables) { msg (SE, _("BY is required when %s is specified."), "TABLE"); goto error; } if (saw_sort) { msg (SE, _("BY is required when %s is specified."), "SORT"); goto error; } } /* Add IN, FIRST, and LAST variables to master dictionary. */ for (i = 0; i < proc.n_files; i++) { struct comb_file *file = &proc.files[i]; if (!create_flag_var ("IN", file->in_name, proc.dict, &file->in_var)) goto error; } if (!create_flag_var ("FIRST", first_name, proc.dict, &proc.first) || !create_flag_var ("LAST", last_name, proc.dict, &proc.last)) goto error; dict_delete_scratch_vars (proc.dict); dict_compact_values (proc.dict); /* Set up mapping from each file's variables to master variables. */ for (i = 0; i < proc.n_files; i++) { struct comb_file *file = &proc.files[i]; size_t src_var_cnt = dict_get_var_cnt (file->dict); size_t j; file->mv = xnmalloc (src_var_cnt, sizeof *file->mv); for (j = 0; j < src_var_cnt; j++) { struct variable *src_var = dict_get_var (file->dict, j); struct variable *dst_var = dict_lookup_var (proc.dict, var_get_name (src_var)); if (dst_var != NULL) { size_t n = subcase_get_n_fields (&file->src); file->mv[n] = var_get_missing_values (src_var); subcase_add_var (&file->src, src_var, SC_ASCEND); subcase_add_var (&file->dst, dst_var, SC_ASCEND); } } } proc.output = autopaging_writer_create (dict_get_proto (proc.dict)); taint = taint_clone (casewriter_get_taint (proc.output)); /* Set up case matcher. */ proc.matcher = case_matcher_create (); for (i = 0; i < proc.n_files; i++) { struct comb_file *file = &proc.files[i]; if (file->reader == NULL) { if (active_file == NULL) { proc_discard_output (ds); file->reader = active_file = proc_open_filtering (ds, false); } else file->reader = casereader_clone (active_file); } if (!file->is_sorted) file->reader = sort_execute (file->reader, &file->by_vars); taint_propagate (casereader_get_taint (file->reader), taint); file->data = casereader_read (file->reader); if (file->type == COMB_FILE) case_matcher_add_input (proc.matcher, &file->by_vars, &file->data, &file->is_minimal); } if (command == COMB_ADD) execute_add_files (&proc); else if (command == COMB_MATCH) execute_match_files (&proc); else if (command == COMB_UPDATE) execute_update (&proc); else NOT_REACHED (); case_matcher_destroy (proc.matcher); proc.matcher = NULL; close_all_comb_files (&proc); if (active_file != NULL) proc_commit (ds); dataset_set_dict (ds, proc.dict); dataset_set_source (ds, casewriter_make_reader (proc.output)); proc.dict = NULL; proc.output = NULL; free_comb_proc (&proc); free (first_name); free (last_name); return taint_destroy (taint) ? CMD_SUCCESS : CMD_CASCADING_FAILURE; error: if (active_file != NULL) proc_commit (ds); free_comb_proc (&proc); taint_destroy (taint); free (first_name); free (last_name); return CMD_CASCADING_FAILURE; }
/* get all xattrs from file given by FILE_NAME or FD (when non-zero). This includes all the user.*, security.*, system.*, etc. available domains */ void xattrs_xattrs_get (int parentfd, char const *file_name, struct tar_stat_info *st, int fd) { if (xattrs_option > 0) { #ifndef HAVE_XATTRS static int done = 0; if (!done) WARN ((0, 0, _("XATTR support is not available"))); done = 1; #else static size_t xsz = 1024; static char *xatrs = NULL; ssize_t xret = -1; if (!xatrs) xatrs = x2nrealloc (xatrs, &xsz, 1); while (((fd == 0) ? ((xret = llistxattrat (parentfd, file_name, xatrs, xsz)) == -1) : ((xret = flistxattr (fd, xatrs, xsz)) == -1)) && (errno == ERANGE)) { xatrs = x2nrealloc (xatrs, &xsz, 1); } if (xret == -1) call_arg_warn ((fd == 0) ? "llistxattrat" : "flistxattr", file_name); else { const char *attr = xatrs; static size_t asz = 1024; static char *val = NULL; if (!val) val = x2nrealloc (val, &asz, 1); while (xret > 0) { size_t len = strlen (attr); ssize_t aret = 0; /* Archive all xattrs during creation, decide at extraction time * which ones are of interest/use for the target filesystem. */ while (((fd == 0) ? ((aret = lgetxattrat (parentfd, file_name, attr, val, asz)) == -1) : ((aret = fgetxattr (fd, attr, val, asz)) == -1)) && (errno == ERANGE)) { val = x2nrealloc (val, &asz, 1); } if (aret != -1) xheader_xattr_add (st, attr, val, aret); else if (errno != ENOATTR) call_arg_warn ((fd == 0) ? "lgetxattrat" : "fgetxattr", file_name); attr += len + 1; xret -= len + 1; } } #endif } }
/* Opens file 'file_name' and reads each line as a flow_mod or a group_mod, * depending on the first keyword on each line. Stores each flow and group * mods in '*bms', an array allocated on the caller's behalf, and the number of * messages in '*n_bms'. * * Returns NULL if successful, otherwise a malloc()'d string describing the * error. The caller is responsible for freeing the returned string. */ char * OVS_WARN_UNUSED_RESULT parse_ofp_bundle_file(const char *file_name, const struct ofputil_port_map *port_map, const struct ofputil_table_map *table_map, struct ofputil_bundle_msg **bms, size_t *n_bms, enum ofputil_protocol *usable_protocols) { size_t allocated_bms; char *error = NULL; int line_number; FILE *stream; struct ds ds; *usable_protocols = OFPUTIL_P_ANY; *bms = NULL; *n_bms = 0; stream = !strcmp(file_name, "-") ? stdin : fopen(file_name, "r"); if (stream == NULL) { return xasprintf("%s: open failed (%s)", file_name, ovs_strerror(errno)); } allocated_bms = *n_bms; ds_init(&ds); line_number = 0; while (!ds_get_preprocessed_line(&ds, stream, &line_number)) { enum ofputil_protocol usable; char *s = ds_cstr(&ds); size_t len; if (*n_bms >= allocated_bms) { struct ofputil_bundle_msg *new_bms; new_bms = x2nrealloc(*bms, &allocated_bms, sizeof **bms); for (size_t i = 0; i < *n_bms; i++) { if (new_bms[i].type == OFPTYPE_GROUP_MOD) { ovs_list_moved(&new_bms[i].gm.buckets, &(*bms)[i].gm.buckets); } } *bms = new_bms; } s += strspn(s, " \t\r\n"); /* Skip white space. */ len = strcspn(s, ", \t\r\n"); /* Get length of the first token. */ if (!strncmp(s, "flow", len)) { s += len; error = parse_ofp_flow_mod_str(&(*bms)[*n_bms].fm, s, port_map, table_map, -2, &usable); if (error) { break; } (*bms)[*n_bms].type = OFPTYPE_FLOW_MOD; } else if (!strncmp(s, "group", len)) { s += len; error = parse_ofp_group_mod_str(&(*bms)[*n_bms].gm, -2, s, port_map, table_map, &usable); if (error) { break; } (*bms)[*n_bms].type = OFPTYPE_GROUP_MOD; } else if (!strncmp(s, "packet-out", len)) { s += len; error = parse_ofp_packet_out_str(&(*bms)[*n_bms].po, s, port_map, table_map, &usable); if (error) { break; } (*bms)[*n_bms].type = OFPTYPE_PACKET_OUT; } else { error = xasprintf("Unsupported bundle message type: %.*s", (int)len, s); break; } *usable_protocols &= usable; /* Each line can narrow the set. */ *n_bms += 1; } ds_destroy(&ds); if (stream != stdin) { fclose(stream); } if (error) { char *err_msg = xasprintf("%s:%d: %s", file_name, line_number, error); free(error); ofputil_free_bundle_msgs(*bms, *n_bms); *bms = NULL; *n_bms = 0; return err_msg; } return NULL; }