mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-03-25 13:29:03 +02:00
Compare commits
8 Commits
f1fda8b43e
...
7ad924a91f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ad924a91f | ||
|
|
50300f846f | ||
|
|
4b35d9ac29 | ||
|
|
1fbe972fa7 | ||
|
|
dcf698b9a0 | ||
|
|
2eee2b5cac | ||
|
|
6d0bb47b82 | ||
|
|
846cb23585 |
@@ -11,14 +11,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
|
||||
/* keep SYS_RENAME 1 to
|
||||
* use libc rename()
|
||||
* recommended
|
||||
*/
|
||||
#ifndef SYS_RENAME
|
||||
#define SYS_RENAME 1
|
||||
#endif
|
||||
|
||||
#define items(x) (sizeof((x)) / sizeof((x)[0]))
|
||||
|
||||
/* system prototypes
|
||||
@@ -43,7 +35,7 @@ int fchmod(int fd, mode_t mode);
|
||||
#define MAX_CMD_LEN 50
|
||||
|
||||
#ifndef PATH_LEN
|
||||
#define PATH_LEN 1024
|
||||
#define PATH_LEN 4096
|
||||
#endif
|
||||
|
||||
#define OFF_ERR 0
|
||||
@@ -67,10 +59,6 @@ int fchmod(int fd, mode_t mode);
|
||||
#define HAVE_REAL_PREAD_PWRITE 0
|
||||
#endif
|
||||
|
||||
#ifndef MAX_EAGAIN_RETRIES
|
||||
#define MAX_EAGAIN_RETRIES 100000
|
||||
#endif
|
||||
|
||||
#ifndef LOOP_EAGAIN
|
||||
#define LOOP_EAGAIN 1
|
||||
#endif
|
||||
@@ -416,7 +404,7 @@ int check_file(int fd, struct stat *st);
|
||||
long rw_over_nrw(long r, unsigned long nrw);
|
||||
#if !defined(HAVE_REAL_PREAD_PWRITE) || \
|
||||
HAVE_REAL_PREAD_PWRITE < 1
|
||||
off_t lseek_loop(int fd, off_t off,
|
||||
off_t lseek_on_eintr(int fd, off_t off,
|
||||
int whence, int loop_eagain, int loop_eintr);
|
||||
#endif
|
||||
int try_err(int loop_err, int errval);
|
||||
@@ -433,16 +421,10 @@ const char *getnvmprogname(void);
|
||||
*/
|
||||
|
||||
char *new_tmpfile(int *fd, int local, const char *path);
|
||||
int x_i_mkstemp(char *template);
|
||||
char *x_c_strrchr(const char *s, int c);
|
||||
int x_i_rename(const char *src, const char *dst);
|
||||
int mkstemp_n(char *template);
|
||||
char *x_c_tmpdir(void);
|
||||
int x_i_close(int fd);
|
||||
void *x_v_memcpy(void *dst,
|
||||
const void *src, unsigned long n);
|
||||
int x_i_memcmp(const void *a,
|
||||
const void *b, unsigned long n);
|
||||
int x_i_fsync(int fd);
|
||||
int close_on_eintr(int fd);
|
||||
int fsync_on_eintr(int fd);
|
||||
|
||||
/* asserts */
|
||||
|
||||
|
||||
@@ -415,17 +415,17 @@ cmd_helper_swap(void)
|
||||
|
||||
check_cmd(cmd_helper_swap, "swap");
|
||||
|
||||
x_v_memcpy(
|
||||
memcpy(
|
||||
f->buf + (unsigned long)GBE_WORK_SIZE,
|
||||
f->buf,
|
||||
GBE_PART_SIZE);
|
||||
|
||||
x_v_memcpy(
|
||||
memcpy(
|
||||
f->buf,
|
||||
f->buf + (unsigned long)GBE_PART_SIZE,
|
||||
GBE_PART_SIZE);
|
||||
|
||||
x_v_memcpy(
|
||||
memcpy(
|
||||
f->buf + (unsigned long)GBE_PART_SIZE,
|
||||
f->buf + (unsigned long)GBE_WORK_SIZE,
|
||||
GBE_PART_SIZE);
|
||||
@@ -442,7 +442,7 @@ cmd_helper_copy(void)
|
||||
|
||||
check_cmd(cmd_helper_copy, "copy");
|
||||
|
||||
x_v_memcpy(
|
||||
memcpy(
|
||||
f->buf + (unsigned long)((f->part ^ 1) * GBE_PART_SIZE),
|
||||
f->buf + (unsigned long)(f->part * GBE_PART_SIZE),
|
||||
GBE_PART_SIZE);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* Safe file handling.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
@@ -66,7 +67,7 @@ xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
|
||||
err(errno, "%s: file not seekable", path);
|
||||
}
|
||||
|
||||
/* Ensure x_i_rename() is durable by syncing the
|
||||
/* Ensure rename() is durable by syncing the
|
||||
* directory containing the target file.
|
||||
*/
|
||||
|
||||
@@ -112,8 +113,8 @@ fsync_dir(const char *path)
|
||||
if (dirbuf == NULL)
|
||||
goto err_fsync_dir;
|
||||
|
||||
x_v_memcpy(dirbuf, path, pathlen + 1);
|
||||
slash = x_c_strrchr(dirbuf, '/');
|
||||
memcpy(dirbuf, path, pathlen + 1);
|
||||
slash = strrchr(dirbuf, '/');
|
||||
|
||||
if (slash != NULL) {
|
||||
*slash = '\0';
|
||||
@@ -146,10 +147,10 @@ fsync_dir(const char *path)
|
||||
}
|
||||
|
||||
/* sync file on disk */
|
||||
if (x_i_fsync(dirfd) == -1)
|
||||
if (fsync_on_eintr(dirfd) == -1)
|
||||
goto err_fsync_dir;
|
||||
|
||||
if (x_i_close(dirfd) == -1)
|
||||
if (close_on_eintr(dirfd) == -1)
|
||||
goto err_fsync_dir;
|
||||
|
||||
if (dirbuf != NULL)
|
||||
@@ -169,7 +170,7 @@ err_fsync_dir:
|
||||
free(dirbuf);
|
||||
|
||||
if (dirfd > -1)
|
||||
x_i_close(dirfd);
|
||||
close_on_eintr(dirfd);
|
||||
|
||||
errno = saved_errno;
|
||||
|
||||
@@ -211,7 +212,7 @@ new_tmpfile(int *fd, int local, const char *path)
|
||||
*/
|
||||
char tmp_none[] = "";
|
||||
char tmp_default[] = "/tmp";
|
||||
char default_tmpname[] = "tmpXXXXXX";
|
||||
char default_tmpname[] = "tmpXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
|
||||
char *tmpname;
|
||||
|
||||
char *base = NULL;
|
||||
@@ -294,22 +295,22 @@ new_tmpfile(int *fd, int local, const char *path)
|
||||
|
||||
*dest = '.'; /* hidden file */
|
||||
|
||||
x_v_memcpy(dest + (unsigned long)1, tmpname, tmpname_len);
|
||||
memcpy(dest + (unsigned long)1, tmpname, tmpname_len);
|
||||
|
||||
x_v_memcpy(dest + (unsigned long)1 + tmpname_len,
|
||||
memcpy(dest + (unsigned long)1 + tmpname_len,
|
||||
default_tmpname, tmpdir_len);
|
||||
} else {
|
||||
|
||||
x_v_memcpy(dest, base, tmpdir_len);
|
||||
memcpy(dest, base, tmpdir_len);
|
||||
|
||||
dest[tmpdir_len] = '/';
|
||||
|
||||
x_v_memcpy(dest + tmpdir_len + 1, tmpname, tmpname_len);
|
||||
memcpy(dest + tmpdir_len + 1, tmpname, tmpname_len);
|
||||
}
|
||||
|
||||
dest[tmppath_len] = '\0';
|
||||
|
||||
fd_tmp = x_i_mkstemp(dest);
|
||||
fd_tmp = mkstemp_n(dest);
|
||||
if (fd_tmp == -1)
|
||||
goto err_new_tmpfile;
|
||||
|
||||
@@ -366,7 +367,7 @@ err_new_tmpfile:
|
||||
free(dest);
|
||||
|
||||
if (fd_tmp > -1)
|
||||
x_i_close(fd_tmp);
|
||||
close_on_eintr(fd_tmp);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -420,36 +421,56 @@ x_c_tmpdir(void)
|
||||
*/
|
||||
|
||||
int
|
||||
x_i_mkstemp(char *template)
|
||||
mkstemp_n(char *template)
|
||||
{
|
||||
int fd;
|
||||
int i, j;
|
||||
unsigned long i, j;
|
||||
unsigned long len;
|
||||
char *p;
|
||||
|
||||
char ch[] =
|
||||
unsigned long xc = 0;
|
||||
|
||||
static char ch[] =
|
||||
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
|
||||
unsigned long r;
|
||||
unsigned long max_len =
|
||||
#ifndef PATH_LEN
|
||||
4096;
|
||||
#else
|
||||
(PATH_LEN);
|
||||
#endif
|
||||
|
||||
len = xstrxlen(template, PATH_LEN);
|
||||
len = xstrxlen(template, max_len);
|
||||
|
||||
/* find trailing XXXXXX */
|
||||
if (len < 6)
|
||||
if (len < 6) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = template + len - 6;
|
||||
p = template + len;
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
while (p > template && p[-1] == 'X') {
|
||||
--p;
|
||||
++xc;
|
||||
}
|
||||
|
||||
for (j = 0; j < 6; j++) {
|
||||
if (xc < 6) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < 200; i++) {
|
||||
|
||||
for (j = 0; j < xc; j++) {
|
||||
|
||||
r = rlong();
|
||||
|
||||
p[j] = ch[(unsigned long)(r >> 1) % (sizeof(ch) - 1)];
|
||||
}
|
||||
|
||||
fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
fd = open(template,
|
||||
O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
|
||||
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
@@ -605,12 +626,6 @@ prw(int fd, void *mem, unsigned long nrw,
|
||||
int loop_eagain, int loop_eintr,
|
||||
int off_reset)
|
||||
{
|
||||
#ifndef MAX_EAGAIN_RETRIES
|
||||
unsigned long retries = 100000;
|
||||
#else
|
||||
unsigned long retries = MAX_EAGAIN_RETRIES;
|
||||
#endif
|
||||
|
||||
long r;
|
||||
int positional_rw;
|
||||
struct stat st;
|
||||
@@ -678,14 +693,14 @@ real_pread_pwrite:
|
||||
HAVE_REAL_PREAD_PWRITE > 0
|
||||
goto real_pread_pwrite;
|
||||
#else
|
||||
if ((off_orig = lseek_loop(fd, (off_t)0, SEEK_CUR,
|
||||
if ((off_orig = lseek_on_eintr(fd, (off_t)0, SEEK_CUR,
|
||||
loop_eagain, loop_eintr)) == (off_t)-1) {
|
||||
r = -1;
|
||||
} else if (lseek_loop(fd, off, SEEK_SET,
|
||||
} else if (lseek_on_eintr(fd, off, SEEK_SET,
|
||||
loop_eagain, loop_eintr) == (off_t)-1) {
|
||||
r = -1;
|
||||
} else {
|
||||
verified = lseek_loop(fd, (off_t)0, SEEK_CUR,
|
||||
verified = lseek_on_eintr(fd, (off_t)0, SEEK_CUR,
|
||||
loop_eagain, loop_eintr);
|
||||
|
||||
/*
|
||||
@@ -700,7 +715,7 @@ real_pread_pwrite:
|
||||
* that nothing is touching it now.
|
||||
*/
|
||||
if (off_reset && off != verified)
|
||||
lseek_loop(fd, off, SEEK_SET,
|
||||
lseek_on_eintr(fd, off, SEEK_SET,
|
||||
loop_eagain, loop_eintr);
|
||||
|
||||
do {
|
||||
@@ -721,7 +736,7 @@ real_pread_pwrite:
|
||||
* will cause an exit, including
|
||||
* per EINTR/EAGAIN re-spin.
|
||||
*/
|
||||
verified = lseek_loop(fd, (off_t)0, SEEK_CUR,
|
||||
verified = lseek_on_eintr(fd, (off_t)0, SEEK_CUR,
|
||||
loop_eagain, loop_eintr);
|
||||
|
||||
if (off != verified)
|
||||
@@ -739,13 +754,12 @@ real_pread_pwrite:
|
||||
|
||||
} while (r == -1 &&
|
||||
(errno == try_err(loop_eintr, EINTR) ||
|
||||
errno == try_err(loop_eagain, EAGAIN)) &&
|
||||
retries++ < MAX_EAGAIN_RETRIES);
|
||||
errno == try_err(loop_eagain, EAGAIN)));
|
||||
}
|
||||
|
||||
saved_errno = errno;
|
||||
|
||||
off_last = lseek_loop(fd, off_orig, SEEK_SET,
|
||||
off_last = lseek_on_eintr(fd, off_orig, SEEK_SET,
|
||||
loop_eagain, loop_eintr);
|
||||
|
||||
if (off_last != off_orig) {
|
||||
@@ -875,12 +889,12 @@ err_rw_over_nrw:
|
||||
#if !defined(HAVE_REAL_PREAD_PWRITE) || \
|
||||
HAVE_REAL_PREAD_PWRITE < 1
|
||||
/*
|
||||
* lseek_loop() does lseek() but optionally
|
||||
* lseek_on_eintr() does lseek() but optionally
|
||||
* on an EINTR/EAGAIN wait loop. Used by prw()
|
||||
* for setting offsets for positional I/O.
|
||||
*/
|
||||
off_t
|
||||
lseek_loop(int fd, off_t off, int whence,
|
||||
lseek_on_eintr(int fd, off_t off, int whence,
|
||||
int loop_eagain, int loop_eintr)
|
||||
{
|
||||
off_t old;
|
||||
@@ -906,65 +920,8 @@ try_err(int loop_err, int errval)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* portable rename(). WARNING:
|
||||
* not powercut-safe. do this to
|
||||
* use system rename:
|
||||
* #define SYS_RENAME 1
|
||||
*
|
||||
* written academically, but in reality,
|
||||
* nearly all unix systems have rename()
|
||||
*/
|
||||
|
||||
int
|
||||
x_i_rename(const char *src, const char *dst)
|
||||
{
|
||||
#if defined(SYS_RENAME) &&\
|
||||
SYS_RENAME > 0
|
||||
return rename(src, dst);
|
||||
#else
|
||||
int sfd, dirfd;
|
||||
ssize_t r;
|
||||
char buf[8192];
|
||||
|
||||
sfd = open(src, O_RDONLY);
|
||||
if (sfd < 0)
|
||||
return -1;
|
||||
|
||||
dirfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (dirfd < 0) {
|
||||
x_i_close(sfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((r = read(sfd, buf, sizeof(buf))) > 0) {
|
||||
ssize_t w = write(dirfd, buf, r);
|
||||
if (w != r) {
|
||||
x_i_close(sfd);
|
||||
x_i_close(dirfd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
x_i_close(sfd);
|
||||
x_i_close(dirfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
x_i_fsync(dirfd);
|
||||
|
||||
x_i_close(sfd);
|
||||
x_i_close(dirfd);
|
||||
|
||||
if (unlink(src) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
x_i_close(int fd)
|
||||
close_on_eintr(int fd)
|
||||
{
|
||||
int r;
|
||||
int saved_errno = errno;
|
||||
@@ -980,7 +937,7 @@ x_i_close(int fd)
|
||||
}
|
||||
|
||||
int
|
||||
x_i_fsync(int fd)
|
||||
fsync_on_eintr(int fd)
|
||||
{
|
||||
int r;
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ copy_gbe(void)
|
||||
if (f->gbe_file_size == SIZE_8KB)
|
||||
return;
|
||||
|
||||
x_v_memcpy(f->buf + (unsigned long)GBE_PART_SIZE,
|
||||
memcpy(f->buf + (unsigned long)GBE_PART_SIZE,
|
||||
f->buf + (unsigned long)(f->gbe_file_size >> 1),
|
||||
(unsigned long)GBE_PART_SIZE);
|
||||
}
|
||||
@@ -125,7 +125,7 @@ read_file(void)
|
||||
|
||||
/* needs sync, for verification
|
||||
*/
|
||||
if (x_i_fsync(f->tmp_fd) == -1)
|
||||
if (fsync_on_eintr(f->tmp_fd) == -1)
|
||||
err(errno, "%s: fsync (tmpfile copy)", f->tname);
|
||||
|
||||
_r = rw_file_exact(f->tmp_fd, f->bufcmp, f->gbe_file_size,
|
||||
@@ -135,7 +135,7 @@ read_file(void)
|
||||
if (_r < 0)
|
||||
err(errno, "%s: read failed (cmp)", f->tname);
|
||||
|
||||
if (x_i_memcmp(f->buf, f->bufcmp, f->gbe_file_size) != 0)
|
||||
if (memcmp(f->buf, f->bufcmp, f->gbe_file_size) != 0)
|
||||
err(errno, "%s: %s: read contents differ (pre-test)",
|
||||
f->fname, f->tname);
|
||||
}
|
||||
@@ -227,7 +227,7 @@ write_to_gbe_bin(void)
|
||||
* We may otherwise read from
|
||||
* cache, so we must sync.
|
||||
*/
|
||||
if (x_i_fsync(f->tmp_fd) == -1)
|
||||
if (fsync_on_eintr(f->tmp_fd) == -1)
|
||||
err(errno, "%s: fsync (pre-verification)",
|
||||
f->tname);
|
||||
|
||||
@@ -246,12 +246,12 @@ write_to_gbe_bin(void)
|
||||
|
||||
saved_errno = errno;
|
||||
|
||||
if (x_i_close(f->tmp_fd) == -1) {
|
||||
if (close_on_eintr(f->tmp_fd) == -1) {
|
||||
fprintf(stderr, "FAIL: %s: close\n", f->tname);
|
||||
f->io_err_gbe_bin = 1;
|
||||
}
|
||||
|
||||
if (x_i_close(f->gbe_fd) == -1) {
|
||||
if (close_on_eintr(f->gbe_fd) == -1) {
|
||||
fprintf(stderr, "FAIL: %s: close\n", f->fname);
|
||||
f->io_err_gbe_bin = 1;
|
||||
}
|
||||
@@ -331,7 +331,7 @@ check_written_part(unsigned long p)
|
||||
f->rw_check_err_read[p] = f->io_err_gbe = 1;
|
||||
else if ((unsigned long)rval != gbe_rw_size)
|
||||
f->rw_check_partial_read[p] = f->io_err_gbe = 1;
|
||||
else if (x_i_memcmp(mem_offset, f->pad, gbe_rw_size) != 0)
|
||||
else if (memcmp(mem_offset, f->pad, gbe_rw_size) != 0)
|
||||
f->rw_check_bad_part[p] = f->io_err_gbe = 1;
|
||||
|
||||
if (f->rw_check_err_read[p] ||
|
||||
@@ -435,7 +435,7 @@ gbe_mv(void)
|
||||
|
||||
saved_errno = errno;
|
||||
|
||||
rval = x_i_rename(f->tname, f->fname);
|
||||
rval = rename(f->tname, f->fname);
|
||||
|
||||
if (rval > -1) {
|
||||
/*
|
||||
@@ -484,13 +484,13 @@ gbe_mv(void)
|
||||
if (rval < 0)
|
||||
goto ret_gbe_mv;
|
||||
|
||||
if (x_i_fsync(dest_fd) == -1)
|
||||
if (fsync_on_eintr(dest_fd) == -1)
|
||||
goto ret_gbe_mv;
|
||||
|
||||
if (x_i_close(dest_fd) == -1)
|
||||
if (close_on_eintr(dest_fd) == -1)
|
||||
goto ret_gbe_mv;
|
||||
|
||||
if (x_i_rename(dest_tmp, f->fname) == -1)
|
||||
if (rename(dest_tmp, f->fname) == -1)
|
||||
goto ret_gbe_mv;
|
||||
|
||||
if (fsync_dir(f->fname) < 0) {
|
||||
@@ -504,7 +504,7 @@ gbe_mv(void)
|
||||
ret_gbe_mv:
|
||||
|
||||
if (f->gbe_fd > -1) {
|
||||
if (x_i_close(f->gbe_fd) < 0)
|
||||
if (close_on_eintr(f->gbe_fd) < 0)
|
||||
rval = -1;
|
||||
if (fsync_dir(f->fname) < 0) {
|
||||
f->io_err_gbe_bin = 1;
|
||||
@@ -514,7 +514,7 @@ ret_gbe_mv:
|
||||
}
|
||||
|
||||
if (f->tmp_fd > -1) {
|
||||
if (x_i_close(f->tmp_fd) < 0)
|
||||
if (close_on_eintr(f->tmp_fd) < 0)
|
||||
rval = -1;
|
||||
|
||||
f->tmp_fd = -1;
|
||||
|
||||
@@ -80,7 +80,7 @@ rlong(void)
|
||||
sizeof(unsigned long), 0, IO_READ, LOOP_EAGAIN,
|
||||
LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR);
|
||||
|
||||
if (x_i_close(fd) < 0)
|
||||
if (close_on_eintr(fd) < 0)
|
||||
err(errno, "Can't close randomness fd");
|
||||
|
||||
if (nr != sizeof(unsigned long))
|
||||
|
||||
@@ -236,7 +236,7 @@ getnvmprogname(void)
|
||||
rval = x->argv0;
|
||||
}
|
||||
|
||||
p = x_c_strrchr(rval, '/');
|
||||
p = strrchr(rval, '/');
|
||||
|
||||
if (p)
|
||||
return p + 1;
|
||||
@@ -260,13 +260,13 @@ exit_cleanup(void)
|
||||
f = &x->f;
|
||||
|
||||
if (f->gbe_fd > -1) {
|
||||
if (x_i_close(f->gbe_fd) == -1)
|
||||
if (close_on_eintr(f->gbe_fd) == -1)
|
||||
close_err = 1;
|
||||
f->gbe_fd = -1;
|
||||
}
|
||||
|
||||
if (f->tmp_fd > -1) {
|
||||
if (x_i_close(f->tmp_fd) == -1)
|
||||
if (close_on_eintr(f->tmp_fd) == -1)
|
||||
close_err = 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -81,43 +81,3 @@ xstrxlen(const char *scmp, unsigned long maxlen)
|
||||
|
||||
return xstr_index;
|
||||
}
|
||||
|
||||
char *
|
||||
x_c_strrchr(const char *s, int c)
|
||||
{
|
||||
const char *p = NULL;
|
||||
|
||||
for ( ; *s; s++)
|
||||
if (*s == (char)c)
|
||||
p = s;
|
||||
|
||||
if (c == '\0')
|
||||
return (char *)s;
|
||||
|
||||
return (char *)p;
|
||||
}
|
||||
|
||||
void *
|
||||
x_v_memcpy(void *dst, const void *src, unsigned long n)
|
||||
{
|
||||
unsigned char *d = (unsigned char *)dst;
|
||||
const unsigned char *s = (const unsigned char *)src;
|
||||
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
int
|
||||
x_i_memcmp(const void *a, const void *b, unsigned long n)
|
||||
{
|
||||
const unsigned char *pa = (const unsigned char *)a;
|
||||
const unsigned char *pb = (const unsigned char *)b;
|
||||
|
||||
for ( ; n--; ++pa, ++pb)
|
||||
if (*pa != *pb)
|
||||
return *pa - *pb;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user