~mrms/osum

1f83a5c7203c852c9780c2dc78f2fbb97f4e711e — Marek Ma┼íkarinec 4 months ago e2329e7
Add stat
2 files changed, 241 insertions(+), 157 deletions(-)

M os.c
M os.um
M os.c => os.c +217 -157
@@ 20,238 20,298 @@
#endif

// fn umc__mkdir(path: string): int
void umc__mkdir(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *path = p[0].ptrVal;
void
umc__mkdir(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[0].ptrVal;

#ifdef _WIN32
  r->intVal = _mkdir(path) ? errno : 0;
	r->intVal = _mkdir(path) ? errno : 0;
#else
  r->intVal = mkdir(path, 0777) ? errno : 0;
	r->intVal = mkdir(path, 0777) ? errno : 0;
#endif
}

// fn umc__remove(path: string): int
void umc__remove(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *path = p[0].ptrVal;
void
umc__remove(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[0].ptrVal;

  r->intVal = remove(path) ? errno : 0;
	r->intVal = remove(path) ? errno : 0;
}

// fn umc__strerror(errno: int): string
void umc__strerror(UmkaStackSlot *p, UmkaStackSlot *r) {
  int errno_ = p[0].intVal;
  UmkaAPI *api = umkaGetAPI(r->ptrVal);
  r->ptrVal = api->umkaMakeStr(r->ptrVal, strerror(errno_));
void
umc__strerror(UmkaStackSlot *p, UmkaStackSlot *r)
{
	int errno_ = p[0].intVal;
	UmkaAPI *api = umkaGetAPI(r->ptrVal);
	r->ptrVal = api->umkaMakeStr(r->ptrVal, strerror(errno_));
}

// fn umc__link(target: str, linkpath: str): int
void umc__link(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *target = p[1].ptrVal;
  char *linkpath = p[0].ptrVal;
  r->intVal = 0;
void
umc__link(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *target = p[1].ptrVal;
	char *linkpath = p[0].ptrVal;
	r->intVal = 0;

#ifdef _WIN32
  struct stat st;
  {
    char sep = '\\';
    char *link_dir = strrchr(linkpath, '\\');
    if (link_dir == NULL) {
      link_dir = strrchr(linkpath, '/');
      sep = '/';
    }

    if (link_dir == NULL)
      link_dir = linkpath;

    size_t link_start_len = link_dir - linkpath;
    char *target_rel = malloc(link_start_len + 1 + strlen(target) + 1);
    if (target_rel == NULL) {
      r->intVal = ENOMEM;
      return;
    }

    memcpy(target_rel, linkpath, link_start_len);
    target_rel[link_start_len] = sep;
    memcpy(target_rel + link_start_len + 1, target, strlen(target) + 1);

    if (stat(target_rel, &st)) {
      r->intVal = errno;
      return;
    }

    free(target_rel);
  }

  DWORD flag = 0x2;
  if (S_ISDIR(st.st_mode))
    flag |= 0x1;
  r->intVal = CreateSymbolicLinkA(linkpath, target, flag) ? 0 : EAGAIN;
	struct stat st;
	{
		char sep = '\\';
		char *link_dir = strrchr(linkpath, '\\');
		if (link_dir == NULL) {
			link_dir = strrchr(linkpath, '/');
			sep = '/';
		}

		if (link_dir == NULL)
			link_dir = linkpath;

		size_t link_start_len = link_dir - linkpath;
		char *target_rel = malloc(link_start_len + 1 + strlen(target) + 1);
		if (target_rel == NULL) {
			r->intVal = ENOMEM;
			return;
		}

		memcpy(target_rel, linkpath, link_start_len);
		target_rel[link_start_len] = sep;
		memcpy(target_rel + link_start_len + 1, target, strlen(target) + 1);

		if (stat(target_rel, &st)) {
			r->intVal = errno;
			return;
		}

		free(target_rel);
	}

	DWORD flag = 0x2;
	if (S_ISDIR(st.st_mode))
		flag |= 0x1;
	r->intVal = CreateSymbolicLinkA(linkpath, target, flag) ? 0 : EAGAIN;
#else
  r->intVal = symlink(target, linkpath) ? errno : 0;
	r->intVal = symlink(target, linkpath) ? errno : 0;
#endif
}

// fn umc__listdir(path: str, files: ^[]str, strArrType: ^void): int
void umc__listdir(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *path = p[2].ptrVal;
  UmkaDynArray(char *) *files = p[1].ptrVal;
  void *str_arr_type = p[0].ptrVal;
  void *umka = r->ptrVal;
  UmkaAPI *api = umkaGetAPI(umka);
void
umc__listdir(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[2].ptrVal;
	UmkaDynArray(char *) *files = p[1].ptrVal;
	void *str_arr_type = p[0].ptrVal;
	void *umka = r->ptrVal;
	UmkaAPI *api = umkaGetAPI(umka);

#ifdef _WIN32
  int count = 0;
  HANDLE hfind;
  WIN32_FIND_DATA data;

  char *path_ = malloc(strlen(path) + 3);
  strcpy(path_, path);
  strcat(path_, "\\*");

  if ((hfind = FindFirstFile(path_, &data)) != INVALID_HANDLE_VALUE) {
    do {
      ++count;
    } while (FindNextFile(hfind, &data));
    FindClose(hfind);
  } else {
    r->intVal = ENOENT;
    return;
  }

  api->umkaMakeDynArray(umka, files, str_arr_type, count);

  hfind = FindFirstFile(path_, &data);
  int i = 0;
  do {
    files->data[i++] = api->umkaMakeStr(umka, data.cFileName);
  } while (FindNextFile(hfind, &data));

  FindClose(hfind);
	int count = 0;
	HANDLE hfind;
	WIN32_FIND_DATA data;

	char *path_ = malloc(strlen(path) + 3);
	strcpy(path_, path);
	strcat(path_, "\\*");

	if ((hfind = FindFirstFile(path_, &data)) != INVALID_HANDLE_VALUE) {
		do {
			++count;
		} while (FindNextFile(hfind, &data));
		FindClose(hfind);
	} else {
		r->intVal = ENOENT;
		return;
	}

	api->umkaMakeDynArray(umka, files, str_arr_type, count);

	hfind = FindFirstFile(path_, &data);
	int i = 0;
	do {
		files->data[i++] = api->umkaMakeStr(umka, data.cFileName);
	} while (FindNextFile(hfind, &data));

	FindClose(hfind);
#else
  struct dirent *e = NULL;
  DIR *d = opendir(path);
  if (d == NULL) {
    r->intVal = errno;
    return;
  }
	struct dirent *e = NULL;
	DIR *d = opendir(path);
	if (d == NULL) {
		r->intVal = errno;
		return;
	}

  long start = telldir(d);
	long start = telldir(d);

  int count = 0;
  while ((e = readdir(d)) != NULL)
    ++count;
	int count = 0;
	while ((e = readdir(d)) != NULL)
		++count;

  api->umkaMakeDynArray(umka, files, str_arr_type, count);
	api->umkaMakeDynArray(umka, files, str_arr_type, count);

  seekdir(d, start);
  for (int i = 0; (e = readdir(d)) != NULL; i++)
    files->data[i] = api->umkaMakeStr(umka, e->d_name);
	seekdir(d, start);
	for (int i = 0; (e = readdir(d)) != NULL; i++)
		files->data[i] = api->umkaMakeStr(umka, e->d_name);

  closedir(d);
	closedir(d);
#endif
  r->intVal = 0;
	r->intVal = 0;
}

// fn umc__isfile(path: str): bool
void umc__isfile(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *path = p[0].ptrVal;
  r->intVal = 0;
void
umc__isfile(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[0].ptrVal;
	r->intVal = 0;

  struct stat st;
  if (stat(path, &st))
    return;
	struct stat st;
	if (stat(path, &st))
		return;

  r->intVal = S_ISREG(st.st_mode);
	r->intVal = S_ISREG(st.st_mode);
}

// fn umc__isdir(path: str): bool
void umc__isdir(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *path = p[0].ptrVal;
  r->intVal = 0;
void
umc__isdir(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[0].ptrVal;
	r->intVal = 0;

  struct stat st;
  if (stat(path, &st))
    return;
	struct stat st;
	if (stat(path, &st))
		return;

  r->intVal = S_ISDIR(st.st_mode);
	r->intVal = S_ISDIR(st.st_mode);
}

// fn umc__islink(path: str): bool
void umc__islink(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *path = p[0].ptrVal;
  r->intVal = 0;
void
umc__islink(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[0].ptrVal;
	r->intVal = 0;

#ifdef _WIN32
  DWORD atts = GetFileAttributes(path);
	DWORD atts = GetFileAttributes(path);

  if (atts == INVALID_FILE_ATTRIBUTES)
    return;
	if (atts == INVALID_FILE_ATTRIBUTES)
		return;

  r->intVal = !!(atts & FILE_ATTRIBUTE_REPARSE_POINT);
	r->intVal = !!(atts & FILE_ATTRIBUTE_REPARSE_POINT);
#else
  struct stat st;
  if (lstat(path, &st))
    return;
	struct stat st;
	if (lstat(path, &st))
		return;

  r->intVal = S_ISLNK(st.st_mode);
	r->intVal = S_ISLNK(st.st_mode);
#endif
}

// fn umc__chmod(path: str, mode: uint32): int
void umc__chmod(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *path = p[1].ptrVal;
  int mode = p[0].intVal;
  r->intVal = chmod(path, mode);
void
umc__chmod(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[1].ptrVal;
	int mode = p[0].intVal;
	r->intVal = chmod(path, mode);
}

// fn umc__get_plat(): Platform
void umc__get_plat(UmkaStackSlot *p, UmkaStackSlot *r) {
void
umc__get_plat(UmkaStackSlot *p, UmkaStackSlot *r)
{
#ifdef _POSIX_VERSION
  r->intVal = 0;
	r->intVal = 0;
#elif defined(_WIN32)
  r->intVal = 1;
	r->intVal = 1;
#elif defined(EMSCRIPTEN)
  r->intVal = 2;
	r->intVal = 2;
#else
  r->intVal = 3;
	r->intVal = 3;
#endif
}

// fn umc__getcwd(out: ^str): Error
void umc__getcwd(UmkaStackSlot *p, UmkaStackSlot *r) {
  char **out = p[0].ptrVal;
  void *umka = r->ptrVal;
  UmkaAPI *api = umkaGetAPI(umka);
  r->intVal = 0;
void
umc__getcwd(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char **out = p[0].ptrVal;
	void *umka = r->ptrVal;
	UmkaAPI *api = umkaGetAPI(umka);
	r->intVal = 0;

  char buf[1024];
	char buf[1024];

#ifdef _WIN32
  if (_getcwd(buf, sizeof(buf)) == NULL) {
    r->intVal = errno;
    return;
  }
	if (_getcwd(buf, sizeof(buf)) == NULL) {
		r->intVal = errno;
		return;
	}
#else
  if (getcwd(buf, sizeof(buf)) == NULL) {
    r->intVal = errno;
    return;
  }
	if (getcwd(buf, sizeof(buf)) == NULL) {
		r->intVal = errno;
		return;
	}
#endif

  *out = api->umkaMakeStr(umka, buf);
	*out = api->umkaMakeStr(umka, buf);
}

// fn umc__setenv(name: str, value: str): int
void umc__setenv(UmkaStackSlot *p, UmkaStackSlot *r) {
  char *name = p[1].ptrVal;
  char *value = p[0].ptrVal;
void
umc__setenv(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *name = p[1].ptrVal;
	char *value = p[0].ptrVal;

#ifdef _WIN32
  if (SetEnvironmentVariable(name, value) == 0) {
    r->intVal = EPERM;
    return;
  }
	if (SetEnvironmentVariable(name, value) == 0) {
		r->intVal = EPERM;
		return;
	}
#else
  r->intVal = setenv(name, value, 1);
	r->intVal = setenv(name, value, 1);
#endif
}

struct umc__statbuf
{
	mode_t mode;
	uint32_t uid;
	uint32_t gid;
	size_t size;
	time_t atime;
	time_t mtime;
	time_t ctime;
};

// fn umc__stat(path: str, buf: ^StatBuf): int
void
umc__stat(UmkaStackSlot *p, UmkaStackSlot *r)
{
	char *path = p[1].ptrVal;
	struct umc__statbuf *buf = p[0].ptrVal;

	struct stat st;

	if (stat(path, &st)) {
		r->intVal = errno;
		return;
	}

	buf->mode = st.st_mode;
	buf->uid = st.st_uid;
	buf->gid = st.st_gid;
	buf->size = st.st_size;
	buf->atime = st.st_atime;
	buf->mtime = st.st_mtime;
	buf->ctime = st.st_ctime;

	r->intVal = 0;
}
\ No newline at end of file

M os.um => os.um +24 -0
@@ 203,6 203,29 @@ fn setEnv*(key: str, value: str): Errno {
	return umc__setenv(key, value)
}

//~~struct StatBuf
type StatBuf* = struct {
//~~
	mode: uint32
	uid: uint32
	gid: uint32
	size: uint
	atime: int
	mtime: int
	ctime: int
}

fn umc__stat(path: str, buf: ^StatBuf): Errno

//~~fn stat
// Get information about a file.
fn stat*(path: str): (StatBuf, Errno) {
//~~
	sb := StatBuf{}
	err := umc__stat(path, &sb)
	return sb, err
}

fn main() {
	printf("Platform: %d\n", getPlatform())
	if cwd, errno := getCwd(); errno != 0 {


@@ 223,6 246,7 @@ fn main() {
	printf("isdir(\"umbox\")    = %v\n", isdir("umbox"))
	printf("islink(\"umbox\")   = %v\n", islink("umbox"))
	printf("islink(\"umbox/filepath/umbox/strings\") = %v\n", islink("umbox/filepath/umbox/strings"))
	printf("stat(\"os.um\") =\n%v\n", stat("os.um"))
	
	printf("Walk dir:\n")
	if errno := walk(".", fn(file: str) {