You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
2.2 KiB

#include "shutil.h"
#include "libutil.h"
#include <err.h>
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
ssize_t
writeall(int fd, const void *buf, size_t n)
{
size_t pos = 0;
while (pos < n) {
ssize_t r = write(fd, (char*)buf + pos, n - pos);
assert(r != 0);
if (r < 0) {
#if !defined(XV6_USER)
if (errno == EINTR)
continue;
#endif
break;
}
pos += r;
}
return pos;
}
ssize_t
readall(int fd, void *buf, size_t n)
{
size_t pos = 0;
while (pos < n) {
ssize_t r = read(fd, (char*)buf + pos, n - pos);
if (r < 0) {
#if !defined(XV6_USER)
if (errno == EINTR)
continue;
#endif
if (pos == 0)
return -1;
break;
}
if (r == 0)
break;
pos += r;
}
return pos;
}
// Read from src until EOF, write to dst. Returns number of bytes
// copied on success, < 0 on failure.
ssize_t
copy_fd(int dst, int src)
{
return copy_fd_n(dst, src, (size_t)-1);
}
// Read from src until EOF or limit bytes, write to dst. Returns
// number of bytes copied on success, < 0 on failure.
ssize_t
copy_fd_n(int dst, int src, size_t limit)
{
size_t res = 0;
char buf[4096];
while (res < limit) {
int r = read(src, buf, limit - res < sizeof buf ? limit - res : sizeof buf);
if (r < 0) {
#if !defined(XV6_USER)
if (errno == EINTR)
continue;
#endif
return r;
}
if (r == 0)
return res;
int r2 = writeall(dst, buf, r);
if (r != r2)
return -1;
res += r;
}
return res;
}
int
mkdir_if_noent(const char *path, mode_t mode)
{
int r = mkdir(path, mode);
if (r < 0) {
#if !defined(XV6_USER)
// xv6 doesn't have errno
if (errno != EEXIST)
return -1;
#endif
}
return 0;
}
// Return the length of the file referred to by fd. Returns < 0 on
// failure.
ssize_t
fd_len(int fd)
{
// Could also do this with fstat, but that returns way more
// information than we need
off_t pos = lseek(fd, 0, SEEK_CUR);
if (pos < 0)
return -1;
off_t end = lseek(fd, 0, SEEK_END);
if (end < 0)
return -1;
if (lseek(fd, pos, SEEK_SET))
edie("failed to return file offset to original position");
return end;
}