Plan 9 from Bell Labs’s /usr/web/sources/contrib/de0u/root/sys/src/cmd/divergefs/file.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#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(&currentpath, 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);
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].