1
/* Functions from hack's utils library.
2
Copyright (C) 1989, 1990, 1991, 1998, 1999, 2003, 2008, 2009, 2011
3
Free Software Foundation, Inc.
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 3, or (at your option)
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
26
#include <sys/types.h>
37
/* Store information about files opened with ck_fopen
38
so that error messages from ck_fread, ck_fwrite, etc. can print the
39
name of the file that had the error */
45
struct open_file *link;
49
static struct open_file *open_files = NULL;
50
static void do_ck_fclose (FILE *fp);
52
/* Print an error message and exit */
55
panic(const char *str, ...)
59
fprintf(stderr, "%s: ", myname);
61
vfprintf(stderr, str, ap);
65
/* Unlink the temporary files. */
70
fclose (open_files->fp);
72
unlink (open_files->name);
74
fprintf (stderr, _("cannot remove %s: %s"), open_files->name, strerror (errno));
77
open_files = open_files->link;
84
/* Internal routine to get a filename from open_files */
85
static const char *utils_fp_name (FILE *fp);
92
for (p=open_files; p; p=p->link)
97
else if (fp == stdout)
99
else if (fp == stderr)
106
register_open_file (fp, name, temp)
112
for (p=open_files; p; p=p->link)
122
p = MALLOC(1, struct open_file);
123
p->link = open_files;
126
p->name = ck_strdup(name);
131
/* Panic on failing fopen */
133
ck_fopen(name, mode, fail)
140
fp = fopen (name, mode);
144
panic(_("couldn't open file %s: %s"), name, strerror(errno));
149
register_open_file (fp, name, false);
153
/* Panic on failing fdopen */
155
ck_fdopen(fd, name, mode, fail)
163
fp = fdopen (fd, mode);
167
panic(_("couldn't attach to %s: %s"), name, strerror(errno));
172
register_open_file (fp, name, false);
177
ck_mkstemp (p_filename, tmpdir, base, mode)
179
const char *base, *tmpdir;
188
tmpdir = getenv("TMPDIR");
191
tmpdir = getenv("TMP");
200
template = xmalloc (strlen (tmpdir) + strlen (base) + 8);
201
sprintf (template, "%s/%sXXXXXX", tmpdir, base);
203
/* The ownership might change, so omit some permissions at first
204
so unauthorized users cannot nip in before the file is ready.
206
mkstemp forces O_BINARY on cygwin, so use mkostemp instead. */
207
save_umask = umask (0700);
208
fd = mkostemp (template, 0);
211
panic(_("couldn't open temporary file %s: %s"), template, strerror(errno));
213
*p_filename = template;
214
fp = fdopen (fd, mode);
215
register_open_file (fp, template, true);
219
/* Panic on failing fwrite */
221
ck_fwrite(ptr, size, nmemb, stream)
228
if (size && fwrite(ptr, size, nmemb, stream) != nmemb)
229
panic(ngettext("couldn't write %d item to %s: %s",
230
"couldn't write %d items to %s: %s", nmemb),
231
nmemb, utils_fp_name(stream), strerror(errno));
234
/* Panic on failing fread */
236
ck_fread(ptr, size, nmemb, stream)
243
if (size && (nmemb=fread(ptr, size, nmemb, stream)) <= 0 && ferror(stream))
244
panic(_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
250
ck_getdelim(text, buflen, buffer_delimiter, stream)
253
char buffer_delimiter;
259
error = ferror (stream);
262
result = getdelim (text, buflen, buffer_delimiter, stream);
263
error = ferror (stream);
267
panic (_("read error on %s: %s"), utils_fp_name(stream), strerror(errno));
272
/* Panic on failing fflush */
277
if (!fwriting(stream))
281
if (fflush(stream) == EOF && errno != EBADF)
282
panic("couldn't flush %s: %s", utils_fp_name(stream), strerror(errno));
285
/* Panic on failing fclose */
291
struct open_file *prev;
292
struct open_file *cur;
294
/* a NULL stream means to close all files */
297
while ( (cur = prev->link) )
299
if (!stream || stream == cur->fp)
301
do_ck_fclose (cur->fp);
302
prev->link = cur->link;
312
/* Also care about stdout, because if it is redirected the
313
last output operations might fail and it is important
314
to signal this as an error (perhaps to make). */
317
do_ck_fclose (stdout);
318
do_ck_fclose (stderr);
322
/* Close a single file. */
330
if (fclose(fp) == EOF)
331
panic("couldn't close %s: %s", utils_fp_name(fp), strerror(errno));
335
/* Follow symlink and panic if something fails. Return the ultimate
336
symlink target, stored in a temporary buffer that the caller should
339
follow_symlink(const char *fname)
341
#ifdef ENABLE_FOLLOW_SYMLINKS
342
static char *buf1, *buf2;
346
const char *buf = fname, *c;
351
buf1 = ck_malloc (PATH_MAX + 1);
352
buf2 = ck_malloc (PATH_MAX + 1);
353
buf_size = PATH_MAX + 1;
356
while ((rc = lstat (buf, &statbuf)) == 0
357
&& (statbuf.st_mode & S_IFLNK) == S_IFLNK)
365
while ((rc = readlink (buf, buf2, buf_size)) == buf_size)
368
buf1 = ck_realloc (buf1, buf_size);
369
buf2 = ck_realloc (buf2, buf_size);
372
panic (_("couldn't follow symlink %s: %s"), buf, strerror(errno));
376
if (buf2[0] != '/' && (c = strrchr (buf, '/')) != NULL)
378
/* Need to handle relative paths with care. Reallocate buf1 and
379
buf2 to be big enough. */
380
int len = c - buf + 1;
381
if (len + rc + 1 > buf_size)
383
buf_size = len + rc + 1;
384
buf1 = ck_realloc (buf1, buf_size);
385
buf2 = ck_realloc (buf2, buf_size);
388
/* Always store the new path in buf1. */
390
memcpy (buf1, buf, len);
392
/* Tack the relative symlink at the end of buf1. */
393
memcpy (buf1 + len, buf2, rc + 1);
398
/* Use buf2 as the buffer, it saves a strcpy if it is not pointing to
399
another link. It works for absolute symlinks, and as long as
400
symlinks do not leave the current directory. */
406
panic (_("cannot stat %s: %s"), buf, strerror(errno));
411
#endif /* ENABLE_FOLLOW_SYMLINKS */
414
/* Panic on failing rename */
416
ck_rename (from, to, unlink_if_fail)
417
const char *from, *to;
418
const char *unlink_if_fail;
420
int rd = rename (from, to);
426
int save_errno = errno;
428
unlink (unlink_if_fail);
430
/* Failure to remove the temporary file is more severe, so trigger it first. */
432
panic (_("cannot remove %s: %s"), unlink_if_fail, strerror (errno));
437
panic (_("cannot rename %s: %s"), from, strerror (errno));
443
/* Panic on failing malloc */
448
void *ret = calloc(1, size ? size : 1);
450
panic("couldn't allocate memory");
454
/* Panic on failing realloc */
456
ck_realloc(ptr, size)
468
return ck_malloc(size);
469
ret = realloc(ptr, size);
471
panic("couldn't re-allocate memory");
475
/* Return a malloc()'d copy of a string */
480
char *ret = MALLOC(strlen(str)+1, char);
481
return strcpy(ret, str);
484
/* Return a malloc()'d copy of a block of memory */
490
void *ret = ck_malloc(len);
491
return memcpy(ret, buf, len);
495
/* Implement a variable sized buffer of `stuff'. We don't know what it is,
496
nor do we care, as long as it doesn't mind being aligned by malloc. */
505
#define MIN_ALLOCATE 50
510
struct buffer *b = MALLOC(1, struct buffer);
511
b->b = MALLOC(MIN_ALLOCATE, char);
512
b->allocated = MIN_ALLOCATE;
531
static void resize_buffer (struct buffer *b, size_t newlen);
533
resize_buffer(b, newlen)
538
size_t alen = b->allocated;
544
try = realloc(b->b, alen); /* Note: *not* the REALLOC() macro! */
548
try = REALLOC(b->b, alen, char);
561
if (b->allocated - b->length < n)
562
resize_buffer(b, b->length+n);
563
result = memcpy(b->b + b->length, p, n);
573
/* This special case should be kept cheap;
574
* don't make it just a mere convenience
575
* wrapper for add_buffer() -- even "builtin"
576
* versions of memcpy(a, b, 1) can become
577
* expensive when called too often.
582
if (b->allocated - b->length < 1)
583
resize_buffer(b, b->length+1);
584
result = b->b + b->length++;