roken: Add rk_undumptext() and support ttys and such
Add rk_undumptext(), which NUL-terminates the contents it reads. rk_undumptext(), and now also rk_undumpdata(), can read from regular and non-regular files (e.g., ttys, pipes, devices, but -on Windows- not sockets). This means that `asn1_print` can now read from `/dev/stdin`, which can be a pipe. There's a way to set a limit on how much to read from non-regular files, and that limit defaults to 10MB. At any rate, the rk_dumpdata(), rk_undumpdata(), and rk_undumptext() functions really do not belong in lib/roken but in lib/base. There are other utility functions in lib/roken that don't belong there too. A rationalization of the split between lib/roken and lib/base is overdue. And while we're at it -lest I forget- it'd be nice to move all the krb5_storage functions out of lib/krb5 and into lib/base, as those could come in handy for, e.g., implementing OpenSSH style certificates and other things outside the krb5 universe.
This commit is contained in:
@@ -51,8 +51,84 @@ rk_dumpdata (const char *filename, const void *buf, size_t size)
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For not-regular files */
|
||||||
|
static int
|
||||||
|
undump_not_file(int fd, char **out, size_t *size, int nul_terminate)
|
||||||
|
{
|
||||||
|
size_t lim = 10 * 1024 * 1024;
|
||||||
|
size_t bufsz = 0;
|
||||||
|
size_t sz = 0;
|
||||||
|
char *buf = NULL;
|
||||||
|
char *tmp;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
if (size && *size != 0 && *size < lim)
|
||||||
|
lim = *size;
|
||||||
|
if (size)
|
||||||
|
*size = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We can't use net_read() if we're on WIN32 because that really wants a
|
||||||
|
* socket FD, which is in a distinct FD namespace from those returned by
|
||||||
|
* open() on Windows.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
ssize_t bytes;
|
||||||
|
|
||||||
|
if (sz == bufsz) {
|
||||||
|
if (bufsz == 0)
|
||||||
|
bufsz = 1024;
|
||||||
|
else
|
||||||
|
bufsz += bufsz >> 1;
|
||||||
|
|
||||||
|
tmp = realloc(buf, bufsz);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
free(buf);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
buf = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = read(fd, buf + sz, bufsz - sz);
|
||||||
|
if (bytes == 0)
|
||||||
|
break;
|
||||||
|
if (bytes < 0 &&
|
||||||
|
(errno == EAGAIN || errno == EWOULDBLOCK))
|
||||||
|
continue;
|
||||||
|
if (bytes < 0)
|
||||||
|
return errno;
|
||||||
|
sz += bytes;
|
||||||
|
} while (sz < lim);
|
||||||
|
|
||||||
|
*out = buf;
|
||||||
|
if (size)
|
||||||
|
*size = sz;
|
||||||
|
|
||||||
|
if (!nul_terminate)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (bufsz > sz) {
|
||||||
|
buf[sz] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = realloc(buf, bufsz + 1);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
free(buf);
|
||||||
|
return ENOMEM;
|
||||||
|
}
|
||||||
|
buf = tmp;
|
||||||
|
buf[sz] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read all data from a filename, care about errors.
|
* Read all data from a file, care about errors.
|
||||||
|
*
|
||||||
|
* If `*size' is not zero and the file is not a regular file, then up to that
|
||||||
|
* many bytes will be read.
|
||||||
|
*
|
||||||
|
* Returns zero on success or a system error code on failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
|
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
|
||||||
@@ -71,6 +147,14 @@ rk_undumpdata(const char *filename, void **buf, size_t *size)
|
|||||||
ret = errno;
|
ret = errno;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
if (!S_ISREG(sb.st_mode)) {
|
||||||
|
char *char_buf;
|
||||||
|
|
||||||
|
ret = undump_not_file(fd, &char_buf, size, 0);
|
||||||
|
(void) close(fd);
|
||||||
|
*buf = char_buf;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (sb.st_size < 0)
|
if (sb.st_size < 0)
|
||||||
sb.st_size = 0;
|
sb.st_size = 0;
|
||||||
@@ -97,3 +181,63 @@ rk_undumpdata(const char *filename, void **buf, size_t *size)
|
|||||||
close(fd);
|
close(fd);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read all text from a file.
|
||||||
|
*
|
||||||
|
* Outputs a C string. It is up to the caller to check for embedded NULs.
|
||||||
|
* The number of bytes read will be stored in `*size' if `size' is not NULL.
|
||||||
|
*
|
||||||
|
* If `size' is not NULL and `*size' is not zero and the file is not a regular
|
||||||
|
* file, then up to that many bytes will be read.
|
||||||
|
*
|
||||||
|
* Returns zero on success or a system error code on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
|
||||||
|
rk_undumptext(const char *filename, char **out, size_t *size)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
int fd, ret;
|
||||||
|
ssize_t sret;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
|
||||||
|
fd = open(filename, O_RDONLY, 0);
|
||||||
|
if (fd < 0 || fstat(fd, &sb) != 0)
|
||||||
|
return errno;
|
||||||
|
if (!S_ISREG(sb.st_mode)) {
|
||||||
|
ret = undump_not_file(fd, out, size, 1);
|
||||||
|
(void) close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb.st_size < 0)
|
||||||
|
sb.st_size = 0;
|
||||||
|
buf = malloc(sb.st_size + 1);
|
||||||
|
if (buf == NULL) {
|
||||||
|
ret = ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (size)
|
||||||
|
*size = sb.st_size;
|
||||||
|
|
||||||
|
sret = read(fd, buf, sb.st_size);
|
||||||
|
if (sret < 0)
|
||||||
|
ret = errno;
|
||||||
|
else if (sret != (ssize_t)sb.st_size)
|
||||||
|
ret = EINVAL;
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (ret) {
|
||||||
|
free(buf);
|
||||||
|
} else {
|
||||||
|
buf[sb.st_size] = '\0';
|
||||||
|
*out = buf;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@@ -532,6 +532,9 @@ rk_dumpdata (const char *, const void *, size_t);
|
|||||||
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
|
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
|
||||||
rk_undumpdata (const char *, void **, size_t *);
|
rk_undumpdata (const char *, void **, size_t *);
|
||||||
|
|
||||||
|
ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL
|
||||||
|
rk_undumptext (const char *, char **, size_t *);
|
||||||
|
|
||||||
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
|
ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
|
||||||
rk_xfree (void *);
|
rk_xfree (void *);
|
||||||
|
|
||||||
|
@@ -171,6 +171,7 @@ HEIMDAL_ROKEN_2.0 {
|
|||||||
rk_tsearch;
|
rk_tsearch;
|
||||||
rk_twalk;
|
rk_twalk;
|
||||||
rk_undumpdata;
|
rk_undumpdata;
|
||||||
|
rk_undumptext;
|
||||||
rk_unparse_flags;
|
rk_unparse_flags;
|
||||||
rk_unparse_time;
|
rk_unparse_time;
|
||||||
rk_unparse_time_approx;
|
rk_unparse_time_approx;
|
||||||
|
Reference in New Issue
Block a user