/* vu-utils.c - vu helper functions
*
****************************************************************
* Copyright (C) 2000 Thomas Lord
*
* See the file "COPYING" for further information about
* the copyright and warranty status of this work.
*/
#include "hackerlab/os/errno.h"
#include "hackerlab/mem/must-malloc.h"
#include "hackerlab/char/str.h"
#include "hackerlab/vu/vu-utils.h"
/************************************************************************
*(h0 "VU Utilities")
*
* These functions provide higher-level abstractions that capture common
* ways of using the lower-level VU functions.
*/
/*(c vu_file_to_string)
* int vu_file_to_string (int * errn,
* t_uchar ** buf,
* size_t * len,
* int fd);
*
* Read the entire contents of `fd' into a newly allocated string.
*
* If no error occurs, return 0. The new string is returned in `*buf';
* its length in `*len'.
*
* If an I/O error occurs, return -1 and fill `*errn'.
*
* If `vu_fstat' is able to report the length of the file, a single call to
* `vu_read_retry' is used to read its contents. Otherwise, repeated calls
* to `vu_read_retry' are used.
*/
int
vu_file_to_string (int * errn,
t_uchar ** buf,
size_t * len,
int fd)
{
struct stat sb;
if (!vu_fstat (errn, fd, &sb))
{
*buf = (t_uchar *)must_malloc (sb.st_size);
if (sb.st_size != vu_read_retry (errn, fd, *buf, sb.st_size))
{
must_free (*buf);
return -1;
}
*len = sb.st_size;
return 0;
}
else
{
#define chunk 8192
size_t total;
*buf = (t_uchar *)must_malloc (chunk);
total = 0;
while (1)
{
ssize_t amt;
amt = vu_read_retry (errn, fd, *buf + total, chunk);
if (amt < 0)
{
must_free (*buf);
return -1;
}
if (amt == 0)
{
*buf = (t_uchar *)must_realloc ((void *)*buf, total);
*len = total;
return 0;
}
total += amt;
*buf = (t_uchar *)must_realloc ((void *)*buf, total + chunk);
}
}
}
/*(c vu_move_fd)
* int vu_move_fd (int * errn, int fd, int newfd);
*
* Relocate `fd' to `newfd'. `fd' must already be handled by VU.
*
* Thus function performs a `vu_dup' or `vu_dup2'
*
* This is useful when performing file redirections after `fork' and
* before `exec'.
*
*/
int
vu_move_fd (int * errn, int fd, int newfd)
{
int ign;
if (fd < 0)
{
*errn = EINVAL;
return -1;
}
if (fd == newfd)
return 0;
if (newfd == -1)
newfd = vu_dup (errn, fd);
else
newfd = vu_dup2 (errn, fd, newfd);
if (newfd < 0)
return -1;
if (0 > vu_move_state (errn, fd, newfd))
{
vu_close (&ign, newfd);
return -1;
}
vu_close (&ign, fd);
return newfd;
}
/*(c vu_file_is_directory)
* int vu_file_is_directory (int * errn, t_uchar * name);
*
* Return 1 if `name' names a directory, 0 if not, -1 on error.
*
* Non-existence of any file called `name' is not an error.
*/
int
vu_file_is_directory (int * errn, t_uchar * name)
{
int e;
struct stat sb;
if (0 > vu_lstat (&e, name, &sb))
{
if (e == ENOENT)
return 0;
*errn = e;
return -1;
}
return (S_ISDIR (sb.st_mode));
}
/*(c vu_file_is_directory_following)
* int vu_file_is_directory_following (int * errn, t_uchar * name);
*
* Return 1 if `name' names a directory or symlink to a directory,
* 0 if not, -1 on error.
*
* Non-existence of any file called `name' is not an error.
*/
int
vu_file_is_directory_following (int * errn, t_uchar * name)
{
int e;
struct stat sb;
if (0 > vu_stat (&e, name, &sb))
{
if (e == ENOENT)
return 0;
*errn = e;
return -1;
}
return (S_ISDIR (sb.st_mode));
}
syntax highlighted by Code2HTML, v. 0.9.1