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
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;
|
|
}
|