#include <u.h>
#include <libc.h>
#include <String.h>
#include <fcall.h>
#include "common.h"
#include "debug.h"
#include "string.h"
#include "filepath.h"
#include "utils.h"
enum
{
DEBUG_FILE = true,
FILE_COPY_BUFFER_SIZE = (8 * 1024)
};
static int fileFdCount = 0;
bool file_copy(int self, int copy)
{
int readsize;
int writtensize;
char buffer[FILE_COPY_BUFFER_SIZE];
assert(fd_isopen(self));
assert(fd_isopen(copy));
while(true)
{
readsize = read(self, buffer, FILE_COPY_BUFFER_SIZE);
if(readsize == 0)
{
return true;
}
if(readsize < 0)
{
ERROR(DEBUG_FILE, "file_copy_fd error reading");
return false;
}
writtensize = write(copy, buffer, readsize);
if(writtensize != readsize)
{
ERROR(DEBUG_FILE, "file_copy_fd error writing file");
return false;
}
}
assert(false); /* impossible to get here */
return false;
}
int file_create(char *self, int omode, ulong perm)
{
int result;
assert_valid(self);
result = create(self, omode, perm);
if(DEBUG_FILE && fd_isopen(result))
{
++fileFdCount;
NOISE(DEBUG_FILE,
"file_create active open: %d path: %s omode: %d perm: %uo fd: %d",
fileFdCount, self, omode, perm, result);
}
return result;
}
int file_open(char *self, int omode)
{
int result;
assert_valid(self);
result = open(self, omode);
if(DEBUG_FILE && fd_isopen(result))
{
++fileFdCount;
NOISE(DEBUG_FILE, "file_open active open: %d path: %s omode: %d fd: %d",
fileFdCount, self, omode, result);
}
return result;
}
void file_close(int self)
{
if(DEBUG_FILE && fd_isopen(self))
{
--fileFdCount;
NOISE(DEBUG_FILE, "file_close active open: %d fd: %d", fileFdCount, self);
}
close(self);
}
bool file_access(char *self, int mode)
{
assert_valid(self);
return access(self, mode) != -1;
}
bool file_exists(char *self)
{
return file_access(self, AEXIST);
}
bool file_mkdir(char *self)
{
int fd;
assert_valid(self);
fd = file_create(self, OREAD, DMDIR | 0777L);
if(!fd_isopen(fd))
{
return false;
}
file_close(fd);
return true;
}
/**
* create any parent directory in order to create the whole restpath directory.
* restpath is being modified to null out each slash while currentpath is kept
* being appended.
*/
bool file_recursive_mkdir(String *currentpath, char *restpath)
{
char *slash;
assert_valid(currentpath);
assert_valid(restpath);
NOISE(DEBUG_FILE,
"entering file_recursive_mkdir with current: %s rest: %s",
s_to_c(currentpath), restpath);
if(*restpath == '\0')
{
NOISE(DEBUG_FILE, "file_recursive_mkdir done");
return true;
}
slash = string_nullify_if_found(restpath, '/');
filepath_append(¤tpath, restpath);
if(!file_exists(s_to_c(currentpath)) && !file_mkdir(s_to_c(currentpath)))
{
ERROR(DEBUG_FILE, "file_recursive_mkdir failed to mkdir %s",
s_to_c(currentpath));
return false;
}
restpath += strlen(restpath);
restpath += (slash != nil) ? 1 : 0;
return file_recursive_mkdir(currentpath, restpath);
}
bool file_relative_recursive_mkdir(char *path)
{
bool result;
String *current = s_copy(".");
assert_valid(path);
result = file_recursive_mkdir(current, path);
s_free(current);
return result;
}
bool file_on_demand_mkdir(char *path)
{
bool result;
char *restpath = estrdup_fs(path);
assert_valid(path);
if(restpath[0] == '/')
{
String *root = s_copy("/");
result = file_recursive_mkdir(root, restpath + 1);
s_free(root);
}
else
{
result = file_relative_recursive_mkdir(restpath);
}
free(restpath);
return result;
}
bool file_remove(char *self)
{
assert_valid(self);
return remove(self) != -1;
}
bool file_dirwstat(char *self, Dir *d)
{
assert_valid(self);
assert_valid(d);
return dirwstat(self, d) != -1;
}
bool file_isdir(char *self)
{
Dir *d;
assert_valid(self);
d = dirstat(self);
if(d != nil)
{
bool result = qid_isdir(&d->qid);
free(d);
return result;
}
return false;
}
long file_dir_file_count(char *self)
{
int fd;
Dir *d;
long result;
assert_valid(self);
fd = file_open(self, OREAD);
if(!fd_isopen(fd))
{
return -1;
}
result = dirreadall(fd, &d);
free(d);
close(fd);
return result;
}
bool file_dir_notempty(char *self)
{
assert_valid(self);
return file_isdir(self) && file_dir_file_count(self) > 0;
}
bool file_isdir_empty(char *self)
{
assert_valid(self);
return !file_dir_notempty(self);
}
|