Home | History | Annotate | Line # | Download | only in patch
util.c revision 1.27.14.1
      1       1.24     joerg /*
      2       1.24     joerg  * $OpenBSD: util.c,v 1.32 2006/03/11 19:41:30 otto Exp $
      3       1.24     joerg  * $DragonFly: src/usr.bin/patch/util.c,v 1.9 2007/09/29 23:11:10 swildner Exp $
      4  1.27.14.1  pgoyette  * $NetBSD: util.c,v 1.27.14.1 2018/06/25 07:26:11 pgoyette Exp $
      5       1.24     joerg  */
      6       1.16    itojun 
      7       1.16    itojun /*
      8       1.24     joerg  * patch - a program to apply diffs to original files
      9       1.24     joerg  *
     10       1.24     joerg  * Copyright 1986, Larry Wall
     11       1.24     joerg  *
     12       1.16    itojun  * Redistribution and use in source and binary forms, with or without
     13       1.24     joerg  * modification, are permitted provided that the following condition is met:
     14       1.24     joerg  * 1. Redistributions of source code must retain the above copyright notice,
     15       1.24     joerg  * this condition and the following disclaimer.
     16       1.24     joerg  *
     17       1.24     joerg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
     18       1.24     joerg  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     19       1.24     joerg  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     20       1.24     joerg  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
     21       1.24     joerg  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22       1.24     joerg  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23       1.24     joerg  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     24       1.24     joerg  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25       1.16    itojun  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26       1.16    itojun  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27       1.16    itojun  * SUCH DAMAGE.
     28       1.24     joerg  *
     29       1.24     joerg  * -C option added in 1998, original code by Marc Espie, based on FreeBSD
     30       1.24     joerg  * behaviour
     31       1.16    itojun  */
     32       1.16    itojun 
     33        1.5  christos #include <sys/cdefs.h>
     34  1.27.14.1  pgoyette __RCSID("$NetBSD: util.c,v 1.27.14.1 2018/06/25 07:26:11 pgoyette Exp $");
     35        1.2   mycroft 
     36       1.12  kristerw #include <sys/param.h>
     37       1.24     joerg #include <sys/stat.h>
     38       1.24     joerg 
     39       1.24     joerg #include <ctype.h>
     40       1.24     joerg #include <errno.h>
     41       1.24     joerg #include <fcntl.h>
     42       1.24     joerg #include <libgen.h>
     43       1.24     joerg #include <signal.h>
     44       1.24     joerg #include <stdarg.h>
     45       1.24     joerg #include <stdlib.h>
     46       1.24     joerg #include <stdio.h>
     47       1.24     joerg #include <string.h>
     48       1.24     joerg #include <unistd.h>
     49       1.12  kristerw 
     50        1.1       cgd #include "common.h"
     51        1.1       cgd #include "util.h"
     52        1.1       cgd #include "backupfile.h"
     53       1.24     joerg #include "pathnames.h"
     54       1.10  kristerw 
     55       1.24     joerg /* Rename a file, copying it if necessary. */
     56        1.1       cgd 
     57        1.1       cgd int
     58       1.24     joerg move_file(const char *from, const char *to)
     59        1.1       cgd {
     60       1.24     joerg 	int	fromfd;
     61       1.24     joerg 	ssize_t	i;
     62       1.21       skd 
     63       1.11  kristerw 	/* to stdout? */
     64        1.1       cgd 
     65       1.11  kristerw 	if (strEQ(to, "-")) {
     66        1.1       cgd #ifdef DEBUGGING
     67       1.11  kristerw 		if (debug & 4)
     68       1.11  kristerw 			say("Moving %s to stdout.\n", from);
     69        1.1       cgd #endif
     70       1.24     joerg 		fromfd = open(from, O_RDONLY);
     71       1.11  kristerw 		if (fromfd < 0)
     72       1.11  kristerw 			pfatal("internal error, can't reopen %s", from);
     73       1.24     joerg 		while ((i = read(fromfd, buf, buf_len)) > 0)
     74       1.24     joerg 			if (write(STDOUT_FILENO, buf, i) != i)
     75       1.11  kristerw 				pfatal("write failed");
     76       1.24     joerg 		close(fromfd);
     77       1.11  kristerw 		return 0;
     78       1.11  kristerw 	}
     79       1.24     joerg 	if (backup_file(to) < 0) {
     80       1.24     joerg 		say("Can't backup %s, output is in %s: %s\n", to, from,
     81       1.24     joerg 		    strerror(errno));
     82       1.24     joerg 		return -1;
     83        1.1       cgd 	}
     84        1.1       cgd #ifdef DEBUGGING
     85        1.1       cgd 	if (debug & 4)
     86       1.11  kristerw 		say("Moving %s to %s.\n", from, to);
     87        1.1       cgd #endif
     88       1.24     joerg 	if (rename(from, to) < 0) {
     89       1.24     joerg 		if (errno != EXDEV || copy_file(from, to) < 0) {
     90       1.11  kristerw 			say("Can't create %s, output is in %s: %s\n",
     91       1.11  kristerw 			    to, from, strerror(errno));
     92       1.11  kristerw 			return -1;
     93       1.11  kristerw 		}
     94        1.1       cgd 	}
     95       1.24     joerg 	return 0;
     96       1.24     joerg }
     97       1.24     joerg 
     98       1.24     joerg /* Backup the original file.  */
     99       1.24     joerg 
    100       1.24     joerg int
    101       1.24     joerg backup_file(const char *orig)
    102       1.24     joerg {
    103       1.24     joerg 	struct stat	filestat;
    104       1.24     joerg 	char		bakname[MAXPATHLEN], *s, *simplename;
    105       1.24     joerg 	dev_t		orig_device;
    106       1.24     joerg 	ino_t		orig_inode;
    107       1.24     joerg 
    108       1.24     joerg 	if (backup_type == none || stat(orig, &filestat) != 0)
    109       1.24     joerg 		return 0;			/* nothing to do */
    110       1.24     joerg 	/*
    111       1.24     joerg 	 * If the user used zero prefixes or suffixes, then
    112       1.24     joerg 	 * he doesn't want backups.  Yet we have to remove
    113       1.24     joerg 	 * orig to break possible hardlinks.
    114       1.24     joerg 	 */
    115       1.24     joerg 	if ((origprae && *origprae == 0) || *simple_backup_suffix == 0) {
    116       1.24     joerg 		unlink(orig);
    117       1.24     joerg 		return 0;
    118       1.24     joerg 	}
    119       1.24     joerg 	orig_device = filestat.st_dev;
    120       1.24     joerg 	orig_inode = filestat.st_ino;
    121       1.24     joerg 
    122       1.24     joerg 	if (origprae) {
    123       1.24     joerg 		if (strlcpy(bakname, origprae, sizeof(bakname)) >= sizeof(bakname) ||
    124       1.24     joerg 		    strlcat(bakname, orig, sizeof(bakname)) >= sizeof(bakname))
    125       1.24     joerg 			fatal("filename %s too long for buffer\n", origprae);
    126       1.24     joerg 	} else {
    127       1.24     joerg 		if ((s = find_backup_file_name(orig)) == NULL)
    128       1.24     joerg 			fatal("out of memory\n");
    129       1.24     joerg 		if (strlcpy(bakname, s, sizeof(bakname)) >= sizeof(bakname))
    130       1.24     joerg 			fatal("filename %s too long for buffer\n", s);
    131       1.24     joerg 		free(s);
    132       1.24     joerg 	}
    133       1.24     joerg 
    134       1.24     joerg 	if ((simplename = strrchr(bakname, '/')) != NULL)
    135       1.24     joerg 		simplename = simplename + 1;
    136       1.24     joerg 	else
    137       1.24     joerg 		simplename = bakname;
    138       1.24     joerg 
    139       1.24     joerg 	/*
    140       1.24     joerg 	 * Find a backup name that is not the same file. Change the
    141       1.24     joerg 	 * first lowercase char into uppercase; if that isn't
    142       1.24     joerg 	 * sufficient, chop off the first char and try again.
    143       1.24     joerg 	 */
    144       1.24     joerg 	while (stat(bakname, &filestat) == 0 &&
    145       1.24     joerg 	    orig_device == filestat.st_dev && orig_inode == filestat.st_ino) {
    146       1.24     joerg 		/* Skip initial non-lowercase chars.  */
    147       1.24     joerg 		for (s = simplename; *s && !islower((unsigned char)*s); s++)
    148       1.24     joerg 			;
    149       1.24     joerg 		if (*s)
    150       1.24     joerg 			*s = toupper((unsigned char)*s);
    151       1.24     joerg 		else
    152       1.24     joerg 			memmove(simplename, simplename + 1,
    153       1.24     joerg 			    strlen(simplename + 1) + 1);
    154       1.24     joerg 	}
    155       1.24     joerg #ifdef DEBUGGING
    156       1.24     joerg 	if (debug & 4)
    157       1.24     joerg 		say("Moving %s to %s.\n", orig, bakname);
    158       1.24     joerg #endif
    159       1.24     joerg 	if (rename(orig, bakname) < 0) {
    160       1.24     joerg 		if (errno != EXDEV || copy_file(orig, bakname) < 0)
    161       1.24     joerg 			return -1;
    162       1.24     joerg 	}
    163       1.11  kristerw 	return 0;
    164       1.11  kristerw }
    165       1.11  kristerw 
    166       1.11  kristerw /*
    167       1.11  kristerw  * Copy a file.
    168       1.11  kristerw  */
    169       1.24     joerg int
    170       1.24     joerg copy_file(const char *from, const char *to)
    171       1.11  kristerw {
    172       1.24     joerg 	int	tofd, fromfd;
    173       1.24     joerg 	ssize_t	i;
    174       1.11  kristerw 
    175       1.24     joerg 	tofd = open(to, O_CREAT|O_TRUNC|O_WRONLY, 0666);
    176       1.11  kristerw 	if (tofd < 0)
    177       1.24     joerg 		return -1;
    178       1.24     joerg 	fromfd = open(from, O_RDONLY, 0);
    179        1.1       cgd 	if (fromfd < 0)
    180       1.11  kristerw 		pfatal("internal error, can't reopen %s", from);
    181       1.24     joerg 	while ((i = read(fromfd, buf, buf_len)) > 0)
    182       1.11  kristerw 		if (write(tofd, buf, i) != i)
    183       1.11  kristerw 			pfatal("write to %s failed", to);
    184       1.24     joerg 	close(fromfd);
    185       1.24     joerg 	close(tofd);
    186       1.24     joerg 	return 0;
    187       1.12  kristerw }
    188       1.12  kristerw 
    189       1.12  kristerw /*
    190       1.24     joerg  * Allocate a unique area for a string.
    191       1.11  kristerw  */
    192        1.1       cgd char *
    193       1.24     joerg savestr(const char *s)
    194        1.1       cgd {
    195       1.24     joerg 	char	*rv;
    196        1.1       cgd 
    197       1.24     joerg 	if (!s)
    198       1.24     joerg 		s = "Oops";
    199       1.24     joerg 	rv = strdup(s);
    200       1.24     joerg 	if (rv == NULL) {
    201       1.24     joerg 		if (using_plan_a)
    202       1.24     joerg 			out_of_mem = true;
    203       1.24     joerg 		else
    204       1.24     joerg 			fatal("out of memory\n");
    205       1.24     joerg 	}
    206       1.24     joerg 	return rv;
    207        1.1       cgd }
    208        1.1       cgd 
    209       1.11  kristerw /*
    210       1.24     joerg  * Vanilla terminal output (buffered).
    211       1.11  kristerw  */
    212        1.1       cgd void
    213       1.24     joerg say(const char *fmt, ...)
    214        1.1       cgd {
    215       1.24     joerg 	va_list	ap;
    216       1.24     joerg 
    217       1.24     joerg 	va_start(ap, fmt);
    218       1.24     joerg 	vfprintf(stderr, fmt, ap);
    219       1.11  kristerw 	va_end(ap);
    220       1.24     joerg 	fflush(stderr);
    221        1.1       cgd }
    222        1.1       cgd 
    223       1.11  kristerw /*
    224       1.11  kristerw  * Terminal output, pun intended.
    225       1.11  kristerw  */
    226       1.24     joerg void
    227       1.24     joerg fatal(const char *fmt, ...)
    228        1.1       cgd {
    229       1.24     joerg 	va_list	ap;
    230       1.24     joerg 
    231       1.24     joerg 	va_start(ap, fmt);
    232       1.11  kristerw 	fprintf(stderr, "patch: **** ");
    233       1.24     joerg 	vfprintf(stderr, fmt, ap);
    234       1.11  kristerw 	va_end(ap);
    235       1.24     joerg 	my_exit(2);
    236        1.1       cgd }
    237        1.1       cgd 
    238       1.11  kristerw /*
    239       1.24     joerg  * Say something from patch, something from the system, then silence . . .
    240       1.11  kristerw  */
    241       1.24     joerg void
    242       1.24     joerg pfatal(const char *fmt, ...)
    243        1.1       cgd {
    244       1.24     joerg 	va_list	ap;
    245       1.24     joerg 	int	errnum = errno;
    246       1.24     joerg 
    247       1.11  kristerw 	fprintf(stderr, "patch: **** ");
    248       1.24     joerg 	va_start(ap, fmt);
    249       1.24     joerg 	vfprintf(stderr, fmt, ap);
    250       1.24     joerg 	va_end(ap);
    251       1.11  kristerw 	fprintf(stderr, ": %s\n", strerror(errnum));
    252       1.24     joerg 	my_exit(2);
    253        1.1       cgd }
    254        1.1       cgd 
    255       1.11  kristerw /*
    256       1.24     joerg  * Get a response from the user via /dev/tty
    257       1.11  kristerw  */
    258        1.1       cgd void
    259       1.24     joerg ask(const char *fmt, ...)
    260        1.1       cgd {
    261       1.24     joerg 	va_list	ap;
    262       1.24     joerg 	ssize_t	nr = 0;
    263       1.24     joerg 	static	int ttyfd = -1;
    264       1.11  kristerw 
    265       1.24     joerg 	va_start(ap, fmt);
    266       1.24     joerg 	vfprintf(stdout, fmt, ap);
    267       1.11  kristerw 	va_end(ap);
    268       1.24     joerg 	fflush(stdout);
    269       1.24     joerg 	if (ttyfd < 0)
    270       1.24     joerg 		ttyfd = open(_PATH_TTY, O_RDONLY);
    271       1.24     joerg 	if (ttyfd >= 0) {
    272       1.24     joerg 		if ((nr = read(ttyfd, buf, buf_len)) > 0 &&
    273       1.24     joerg 		    buf[nr - 1] == '\n')
    274       1.24     joerg 			buf[nr - 1] = '\0';
    275       1.24     joerg 	}
    276       1.24     joerg 	if (ttyfd < 0 || nr <= 0) {
    277       1.24     joerg 		/* no tty or error reading, pretend user entered 'return' */
    278       1.24     joerg 		putchar('\n');
    279       1.24     joerg 		buf[0] = '\0';
    280       1.11  kristerw 	}
    281        1.1       cgd }
    282        1.1       cgd 
    283       1.11  kristerw /*
    284       1.11  kristerw  * How to handle certain events when not in a critical region.
    285       1.11  kristerw  */
    286        1.1       cgd void
    287        1.9  kristerw set_signals(int reset)
    288        1.1       cgd {
    289       1.24     joerg 	static sig_t	hupval, intval;
    290        1.1       cgd 
    291       1.11  kristerw 	if (!reset) {
    292       1.11  kristerw 		hupval = signal(SIGHUP, SIG_IGN);
    293       1.11  kristerw 		if (hupval != SIG_IGN)
    294       1.24     joerg 			hupval = my_exit;
    295       1.11  kristerw 		intval = signal(SIGINT, SIG_IGN);
    296       1.11  kristerw 		if (intval != SIG_IGN)
    297       1.24     joerg 			intval = my_exit;
    298       1.11  kristerw 	}
    299       1.24     joerg 	signal(SIGHUP, hupval);
    300       1.24     joerg 	signal(SIGINT, intval);
    301        1.1       cgd }
    302        1.1       cgd 
    303       1.11  kristerw /*
    304       1.11  kristerw  * How to handle certain events when in a critical region.
    305       1.11  kristerw  */
    306        1.1       cgd void
    307       1.24     joerg ignore_signals(void)
    308        1.1       cgd {
    309       1.24     joerg 	signal(SIGHUP, SIG_IGN);
    310       1.24     joerg 	signal(SIGINT, SIG_IGN);
    311        1.1       cgd }
    312        1.1       cgd 
    313       1.11  kristerw /*
    314       1.24     joerg  * Make sure we'll have the directories to create a file. If `striplast' is
    315       1.24     joerg  * true, ignore the last element of `filename'.
    316       1.11  kristerw  */
    317       1.24     joerg 
    318        1.1       cgd void
    319       1.24     joerg makedirs(const char *filename, bool striplast)
    320        1.1       cgd {
    321       1.24     joerg 	char	*tmpbuf;
    322       1.24     joerg 
    323       1.24     joerg 	if ((tmpbuf = strdup(filename)) == NULL)
    324       1.24     joerg 		fatal("out of memory\n");
    325       1.11  kristerw 
    326       1.24     joerg 	if (striplast) {
    327       1.24     joerg 		char	*s = strrchr(tmpbuf, '/');
    328       1.25     joerg 		if (s == NULL) {
    329       1.25     joerg 			free(tmpbuf);
    330       1.24     joerg 			return;	/* nothing to be done */
    331       1.25     joerg 		}
    332       1.24     joerg 		*s = '\0';
    333       1.24     joerg 	}
    334       1.24     joerg 	if (mkpath(tmpbuf) != 0)
    335       1.24     joerg 		pfatal("creation of %s failed", tmpbuf);
    336       1.24     joerg 	free(tmpbuf);
    337        1.1       cgd }
    338        1.1       cgd 
    339       1.11  kristerw /*
    340       1.11  kristerw  * Make filenames more reasonable.
    341       1.11  kristerw  */
    342        1.1       cgd char *
    343       1.24     joerg fetchname(const char *at, bool *exists, int strip_leading)
    344        1.1       cgd {
    345       1.24     joerg 	char		*fullname, *name, *t;
    346       1.24     joerg 	int		sleading, tab;
    347       1.24     joerg 	struct stat	filestat;
    348       1.11  kristerw 
    349       1.24     joerg 	if (at == NULL || *at == '\0')
    350       1.11  kristerw 		return NULL;
    351       1.11  kristerw 	while (isspace((unsigned char)*at))
    352       1.11  kristerw 		at++;
    353        1.1       cgd #ifdef DEBUGGING
    354       1.11  kristerw 	if (debug & 128)
    355       1.24     joerg 		say("fetchname %s %d\n", at, strip_leading);
    356        1.1       cgd #endif
    357       1.24     joerg 	/* So files can be created by diffing against /dev/null.  */
    358       1.24     joerg 	if (strnEQ(at, _PATH_DEVNULL, sizeof(_PATH_DEVNULL) - 1))
    359       1.11  kristerw 		return NULL;
    360       1.24     joerg 	name = fullname = t = savestr(at);
    361       1.11  kristerw 
    362       1.24     joerg 	tab = strchr(t, '\t') != NULL;
    363       1.24     joerg 	/* Strip off up to `strip_leading' path components and NUL terminate. */
    364       1.24     joerg 	for (sleading = strip_leading; *t != '\0' && ((tab && *t != '\t') ||
    365       1.24     joerg 	    !isspace((unsigned char)*t)); t++) {
    366       1.24     joerg 		if (t[0] == '/' && t[1] != '/' && t[1] != '\0')
    367       1.11  kristerw 			if (--sleading >= 0)
    368       1.11  kristerw 				name = t + 1;
    369       1.24     joerg 	}
    370       1.11  kristerw 	*t = '\0';
    371       1.11  kristerw 
    372       1.11  kristerw 	/*
    373       1.24     joerg 	 * If no -p option was given (957 is the default value!), we were
    374       1.24     joerg 	 * given a relative pathname, and the leading directories that we
    375       1.24     joerg 	 * just stripped off all exist, put them back on.
    376       1.11  kristerw 	 */
    377       1.11  kristerw 	if (strip_leading == 957 && name != fullname && *fullname != '/') {
    378       1.11  kristerw 		name[-1] = '\0';
    379       1.24     joerg 		if (stat(fullname, &filestat) == 0 && S_ISDIR(filestat.st_mode)) {
    380       1.11  kristerw 			name[-1] = '/';
    381       1.11  kristerw 			name = fullname;
    382       1.11  kristerw 		}
    383       1.11  kristerw 	}
    384       1.24     joerg 	name = savestr(name);
    385       1.24     joerg 	free(fullname);
    386       1.24     joerg 
    387       1.24     joerg 	*exists = stat(name, &filestat) == 0;
    388       1.24     joerg 	return name;
    389       1.24     joerg }
    390       1.24     joerg 
    391       1.24     joerg /*
    392       1.24     joerg  * Takes the name returned by fetchname and looks in RCS/SCCS directories
    393       1.24     joerg  * for a checked in version.
    394       1.24     joerg  */
    395       1.24     joerg char *
    396       1.24     joerg checked_in(char *file)
    397       1.24     joerg {
    398       1.24     joerg 	char		*filebase, *filedir, tmpbuf[MAXPATHLEN];
    399       1.24     joerg 	struct stat	filestat;
    400       1.11  kristerw 
    401       1.24     joerg 	filebase = basename(file);
    402       1.24     joerg 	filedir = dirname(file);
    403       1.24     joerg 
    404       1.24     joerg #define try(f, a1, a2, a3) \
    405       1.24     joerg (snprintf(tmpbuf, sizeof tmpbuf, f, a1, a2, a3), stat(tmpbuf, &filestat) == 0)
    406       1.24     joerg 
    407       1.24     joerg 	if (try("%s/RCS/%s%s", filedir, filebase, RCSSUFFIX) ||
    408       1.24     joerg 	    try("%s/RCS/%s%s", filedir, filebase, "") ||
    409       1.24     joerg 	    try("%s/%s%s", filedir, filebase, RCSSUFFIX) ||
    410       1.24     joerg 	    try("%s/SCCS/%s%s", filedir, SCCSPREFIX, filebase) ||
    411       1.24     joerg 	    try("%s/%s%s", filedir, SCCSPREFIX, filebase))
    412       1.24     joerg 		return file;
    413       1.24     joerg 
    414       1.24     joerg 	return NULL;
    415       1.24     joerg }
    416       1.11  kristerw 
    417       1.24     joerg void
    418       1.24     joerg version(void)
    419       1.24     joerg {
    420       1.26       wiz 	printf("Patch version 2.0-12u8-NetBSD\n");
    421       1.24     joerg 	my_exit(EXIT_SUCCESS);
    422       1.24     joerg }
    423        1.1       cgd 
    424       1.24     joerg /*
    425       1.24     joerg  * Exit with cleanup.
    426       1.24     joerg  */
    427       1.24     joerg void
    428       1.24     joerg my_exit(int status)
    429       1.24     joerg {
    430       1.24     joerg 	unlink(TMPINNAME);
    431       1.24     joerg 	if (!toutkeep)
    432       1.24     joerg 		unlink(TMPOUTNAME);
    433       1.24     joerg 	if (!trejkeep)
    434       1.24     joerg 		unlink(TMPREJNAME);
    435       1.24     joerg 	unlink(TMPPATNAME);
    436       1.24     joerg 	exit(status);
    437        1.1       cgd }
    438  1.27.14.1  pgoyette 
    439  1.27.14.1  pgoyette void *
    440  1.27.14.1  pgoyette pch_realloc(void *ptr, size_t number, size_t size)
    441  1.27.14.1  pgoyette {
    442  1.27.14.1  pgoyette 	if (number > SIZE_MAX / size) {
    443  1.27.14.1  pgoyette 		errno = EOVERFLOW;
    444  1.27.14.1  pgoyette 		return NULL;
    445  1.27.14.1  pgoyette 	}
    446  1.27.14.1  pgoyette 	return realloc(ptr, number * size);
    447  1.27.14.1  pgoyette }
    448