char * xgetcwd () { #if HAVE_GETCWD_NULL char *cwd = getcwd (NULL, 0); if (! cwd && errno == ENOMEM) xalloc_die (); return cwd; #else /* The initial buffer size for the working directory. A power of 2 detects arithmetic overflow earlier, but is not required. */ # ifndef INITIAL_BUFFER_SIZE # define INITIAL_BUFFER_SIZE 128 # endif size_t buf_size = INITIAL_BUFFER_SIZE; while (1) { char *buf = xmalloc (buf_size); char *cwd = getcwd (buf, buf_size); int saved_errno; if (cwd) return cwd; saved_errno = errno; free (buf); if (saved_errno != ERANGE) return NULL; buf_size *= 2; if (buf_size == 0) xalloc_die (); } #endif }
static char * savedirstream (DIR *dirp) { char *name_space; size_t allocated = NAME_SIZE_DEFAULT; size_t used = 0; int save_errno; if (dirp == NULL) return NULL; name_space = xmalloc (allocated); 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 (used + entry_size < used) xalloc_die (); if (allocated <= used + entry_size) { do { if (2 * allocated < allocated) xalloc_die (); allocated *= 2; } while (allocated <= used + entry_size); name_space = xrealloc (name_space, allocated); } memcpy (name_space + used, entry, entry_size); used += entry_size; } } name_space[used] = '\0'; save_errno = errno; if (closedir (dirp) != 0) save_errno = errno; if (save_errno != 0) { free (name_space); errno = save_errno; return NULL; } return name_space; }
char * savedir (const char *dir) { DIR *dirp; struct dirent *dp; char *name_space; size_t allocated = NAME_SIZE_DEFAULT; size_t used = 0; int save_errno; dirp = opendir (dir); if (dirp == NULL) return NULL; name_space = xmalloc (allocated); errno = 0; while ((dp = readdir (dirp)) != NULL) { /* Skip "", ".", and "..". "" is returned by at least one buggy implementation: Solaris 2.4 readdir on NFS filesystems. */ char const *entry = dp->d_name; if (entry[entry[0] != '.' ? 0 : entry[1] != '.' ? 1 : 2] != '\0') { size_t entry_size = strlen (entry) + 1; if (used + entry_size < used) xalloc_die (); if (allocated <= used + entry_size) { do { if (2 * allocated < allocated) xalloc_die (); allocated *= 2; } while (allocated <= used + entry_size); name_space = xrealloc (name_space, allocated); } memcpy (name_space + used, entry, entry_size); used += entry_size; } } name_space[used] = '\0'; save_errno = errno; if (CLOSEDIR (dirp) != 0) save_errno = errno; if (save_errno != 0) { free (name_space); errno = save_errno; return NULL; } return name_space; }
bool read_files (struct file_data filevec[], bool pretend_binary) { int i; bool skip_test = text | pretend_binary; bool appears_binary = pretend_binary | sip (&filevec[0], skip_test); if (filevec[0].desc != filevec[1].desc) appears_binary |= sip (&filevec[1], skip_test | appears_binary); else { filevec[1].buffer = filevec[0].buffer; filevec[1].bufsize = filevec[0].bufsize; filevec[1].buffered = filevec[0].buffered; } if (appears_binary) { set_binary_mode (filevec[0].desc, true); set_binary_mode (filevec[1].desc, true); return true; } find_identical_ends (filevec); equivs_alloc = filevec[0].alloc_lines + filevec[1].alloc_lines + 1; if (PTRDIFF_MAX / sizeof *equivs <= equivs_alloc) xalloc_die (); equivs = xmalloc (equivs_alloc * sizeof *equivs); /* Equivalence class 0 is permanently safe for lines that were not hashed. Real equivalence classes start at 1. */ equivs_index = 1; /* Allocate (one plus) a prime number of hash buckets. Use a prime number between 1/3 and 2/3 of the value of equiv_allocs, approximately. */ for (i = 9; (size_t) 1 << i < equivs_alloc / 3; i++) continue; nbuckets = ((size_t) 1 << i) - prime_offset[i]; if (PTRDIFF_MAX / sizeof *buckets <= nbuckets) xalloc_die (); buckets = zalloc ((nbuckets + 1) * sizeof *buckets); buckets++; for (i = 0; i < 2; i++) find_and_hash_each_line (&filevec[i]); filevec[0].equiv_max = filevec[1].equiv_max = equivs_index; free (equivs); free (buckets - 1); return false; }
static void time_to_env (char *envar, struct timespec t) { char buf[TIMESPEC_STRSIZE_BOUND]; if (setenv (envar, code_timespec (t, buf), 1) != 0) xalloc_die (); }
int main (int argc _GL_UNUSED, char **argv) { set_program_name (argv[0]); xalloc_die (); return 0; }
static inline void * xnrealloc_inline (void *p, size_t n, size_t s) { if (xalloc_oversized (n, s) || (! (p = realloc (p, n * s)) && n != 0)) xalloc_die (); return p; }
static inline void * x2nrealloc_inline (void *p, size_t *pn, size_t s) { size_t n = *pn; if (! p) { if (! n) { /* The approximate size to use for initial small allocation requests, when the invoking code specifies an old size of zero. 64 bytes is the largest "small" request for the GNU C library malloc. */ enum { DEFAULT_MXFAST = 64 }; n = DEFAULT_MXFAST / s; n += !n; } } else { if (SIZE_MAX / 2 / s < n) xalloc_die (); n *= 2; } *pn = n; return xrealloc (p, n * s); }
char *xstrdup(const char *s1) { char *s = strdup(s1); if (s1 && !s) xalloc_die(); return s; }
void *xmalloc(size_t size) { void *ptr = malloc(size); if (size && !ptr) xalloc_die(); return ptr; }
/* Create a vector of N_VECS bitsets, each of N_BITS, and of type TYPE. */ bitset * bitsetv_alloc (bitset_bindex n_vecs, bitset_bindex n_bits, enum bitset_type type) { size_t vector_bytes; size_t bytes; bitset *bsetv; bitset_bindex i; /* Determine number of bytes for each set. */ bytes = bitset_bytes (type, n_bits); /* If size calculation overflows, memory is exhausted. */ if (BITSET_SIZE_MAX / (sizeof (bitset) + bytes) <= n_vecs) xalloc_die (); /* Allocate vector table at head of bitset array. */ vector_bytes = (n_vecs + 1) * sizeof (bitset) + bytes - 1; vector_bytes -= vector_bytes % bytes; bsetv = xcalloc (1, vector_bytes + bytes * n_vecs); for (i = 0; i < n_vecs; i++) { bsetv[i] = (bitset) (void *) ((char *) bsetv + vector_bytes + i * bytes); bitset_init (bsetv[i], n_bits, type); } /* Null terminate table. */ bsetv[i] = 0; return bsetv; }
FTS * xfts_open (char * const *argv, int options, int (*compar) (const FTSENT **, const FTSENT **)) { FTS *fts = fts_open (argv, options | FTS_CWDFD, compar); if (fts == NULL) { /* This can fail in three ways: out of memory, invalid bit_flags, and one or more of the FILES is an empty string. We could try to decipher that errno==EINVAL means invalid bit_flags and errno==ENOENT means there's an empty string, but that seems wrong. Ideally, fts_open would return a proper error indicator. For now, we'll presume that the bit_flags are valid and just check for empty strings. */ bool invalid_arg = false; for (; *argv; ++argv) { if (**argv == '\0') invalid_arg = true; } if (invalid_arg) error (EXIT_FAILURE, 0, _("invalid argument: %s"), quote ("")); else xalloc_die (); } return fts; }
/* Record file, FILE, and dev/ino from *STATS, in the hash table, HT. If HT is NULL, return immediately. If memory allocation fails, exit immediately. */ void record_file (Hash_table *ht, char const *file, struct stat const *stats) { struct F_triple *ent; if (ht == NULL) return; ent = xmalloc (sizeof *ent); ent->name = xstrdup (file); ent->st_ino = stats->st_ino; ent->st_dev = stats->st_dev; { struct F_triple *ent_from_table = hash_insert (ht, ent); if (ent_from_table == NULL) { /* Insertion failed due to lack of memory. */ xalloc_die (); } if (ent_from_table != ent) { /* There was alread a matching entry in the table, so ENT was not inserted. Free it. */ triple_free (ent); } } }
/* Return zero if TABLE contains a LEN-character long prefix of STRING, otherwise, insert a newly allocated copy of this prefix to TABLE and return 1. If RETURN_PREFIX is not NULL, point it to the allocated copy. */ static bool hash_string_insert_prefix (Hash_table **table, char const *string, size_t len, const char **return_prefix) { Hash_table *t = *table; char *s; char *e; if (len) { s = xmalloc (len + 1); memcpy (s, string, len); s[len] = 0; } else s = xstrdup (string); if (! ((t || (*table = t = hash_initialize (0, 0, hash_string_hasher, hash_string_compare, 0))) && (e = hash_insert (t, s)))) xalloc_die (); if (e == s) { if (return_prefix) *return_prefix = s; return 1; } else { free (s); return 0; } }
dico_stream_t xdico_transcript_stream_create(dico_stream_t transport, dico_stream_t logstr, const char *prefix[]) { struct transcript_stream *p = xmalloc(sizeof(*p)); dico_stream_t stream; int rc = dico_stream_create(&stream, DICO_STREAM_READ|DICO_STREAM_WRITE, p); if (rc) xalloc_die(); p->flags = TRANS_READ | TRANS_WRITE; if (prefix) { p->prefix[0] = xstrdup(prefix[0] ? prefix[0] : default_prefix[0]); p->prefix[1] = xstrdup(prefix[1] ? prefix[1] : default_prefix[1]); } else { p->prefix[0] = xstrdup(default_prefix[0]); p->prefix[1] = xstrdup(default_prefix[1]); } p->transport = transport; p->logstr = logstr; dico_stream_set_read(stream, transcript_read); dico_stream_set_write(stream, transcript_write); dico_stream_set_flush(stream, transcript_flush); dico_stream_set_close(stream, transcript_close); dico_stream_set_destroy(stream, transcript_destroy); dico_stream_set_ioctl(stream, transcript_ioctl); dico_stream_set_error_string(stream, transcript_strerror); dico_stream_set_buffer(stream, dico_buffer_line, 1024); return stream; }
void *xmalloc (size_t size) { void *mem = malloc(size); if (mem == NULL) xalloc_die(); return mem; }
void *xrealloc (void *ptr, size_t size) { void *mem = realloc(ptr, size); if (mem == NULL) xalloc_die(); return mem; }
void *xnrealloc( void *p, size_t n, size_t s ) { int edx; if ( (long long)0xffffffff / s < n ) xalloc_die( ); return xrealloc( p, s * n ); }
extern char * remember_copied (const char *name, ino_t ino, dev_t dev) { struct Src_to_dest *ent; struct Src_to_dest *ent_from_table; ent = xmalloc (sizeof *ent); ent->name = xstrdup (name); ent->st_ino = ino; ent->st_dev = dev; ent_from_table = hash_insert (src_to_dest, ent); if (ent_from_table == NULL) { /* Insertion failed due to lack of memory. */ xalloc_die (); } /* Determine whether there was already an entry in the table with a matching key. If so, free ENT (it wasn't inserted) and return the `name' from the table entry. */ if (ent_from_table != ent) { src_to_dest_free (ent); return (char *) ent_from_table->name; } /* New key; insertion succeeded. */ return NULL; }
int alias_install(const char *kw, int argc, char **argv, grecs_locus_t *ploc) { struct alias *sample = xmalloc(sizeof(*sample)), *ap; sample->kw = xstrdup(kw); sample->argc = argc; sample->argv = argv; sample->locus = *ploc; if (! ((alias_table || (alias_table = hash_initialize(0, 0, alias_hasher, alias_compare, NULL))) && (ap = hash_insert(alias_table, sample)))) xalloc_die(); if (ap != sample) { free(sample->kw); free(sample); grecs_error(ploc, 0, _("alias `%s' already defined"), kw); grecs_error(&ap->locus, 0, _("this is the location of the previous definition")); return 1; /* Found */ } return 0; }
void *xnmalloc( size_t n, size_t s ) { int edx; if ( (long long)0xffffffff / s < n ) xalloc_die( ); return xmalloc( s * n ); }
/* Allocates and returns N * M bytes of memory. */ static void * xnmalloc (size_t n, size_t m) { if ((size_t) -1 / m <= n) xalloc_die (); return xmalloc (n * m); }
static bool get_group_info (struct group_info *gi) { int n_groups; int n_group_slots = getgroups (0, NULL); GETGROUPS_T *group; if (n_group_slots < 0) return false; /* Avoid xnmalloc, as it goes awry when SIZE_MAX < n_group_slots. */ if (xalloc_oversized (n_group_slots, sizeof *group)) xalloc_die (); group = xmalloc (n_group_slots * sizeof *group); n_groups = getgroups (n_group_slots, group); /* In case of error, the user loses. */ if (n_groups < 0) { free (group); return false; } gi->n_groups = n_groups; gi->group = group; return true; }
/* Check if FILE_NAME already exists and make a backup of it right now. Return success (nonzero) only if the backup is either unneeded, or successful. For now, directories are considered to never need backup. If THIS_IS_THE_ARCHIVE is nonzero, this is the archive and so, we do not have to backup block or character devices, nor remote entities. */ bool maybe_backup_file (const char *file_name, bool this_is_the_archive) { struct stat file_stat; assign_string (&before_backup_name, file_name); /* A run situation may exist between Emacs or other GNU programs trying to make a backup for the same file simultaneously. If theoretically possible, real problems are unlikely. Doing any better would require a convention, GNU-wide, for all programs doing backups. */ assign_string (&after_backup_name, 0); /* Check if we really need to backup the file. */ if (this_is_the_archive && _remdev (file_name)) return true; if (deref_stat (file_name, &file_stat) != 0) { if (errno == ENOENT) return true; stat_error (file_name); return false; } if (S_ISDIR (file_stat.st_mode)) return true; if (this_is_the_archive && (S_ISBLK (file_stat.st_mode) || S_ISCHR (file_stat.st_mode))) return true; after_backup_name = find_backup_file_name (file_name, backup_type); if (! after_backup_name) xalloc_die (); if (renameat (chdir_fd, before_backup_name, chdir_fd, after_backup_name) == 0) { if (verbose_option) fprintf (stdlis, _("Renaming %s to %s\n"), quote_n (0, before_backup_name), quote_n (1, after_backup_name)); return true; } else { /* The backup operation failed. */ int e = errno; ERROR ((0, e, _("%s: Cannot rename to %s"), quotearg_colon (before_backup_name), quote_n (1, after_backup_name))); assign_string (&after_backup_name, 0); return false; } }
char * xgetcwd (void) { char *cwd = getcwd (NULL, 0); if (! cwd && errno == ENOMEM) xalloc_die (); return cwd; }
void init_backup_hash_table (void) { file_id_table = hash_initialize (0, NULL, file_id_hasher, file_id_comparator, free); if (!file_id_table) xalloc_die (); }
int xgetgroups (char const *username, gid_t gid, gid_t **groups) { int result = mgetgroups (username, gid, groups); if (result == -1 && errno == ENOMEM) xalloc_die (); return result; }
char * xpath_concat (const char *dir, const char *base, char **base_in_result) { char *res = path_concat (dir, base, base_in_result); if (! res) xalloc_die (); return res; }
char * xreadlink (char const *filename) { char *result = areadlink (filename); if (result == NULL && errno == ENOMEM) xalloc_die (); return result; }
void * xmalloc (size_t n) { void *p = malloc (n); if (!p && n != 0) xalloc_die (); return p; }