File System

#import "std/fs"

File system module for manipulation with files and directories. This module provides an abstraction over operating system APIs such as creating files and directories, reading and writing, and scanning the filesystem.

FileStream

FileStream :: struct #base Stream {
    handle: _File;
}

File: fs.bl

FILE_INVALID

FILE_INVALID :: _FILE_INVALID

Invalid file handle. This can be used for file handle validation.

File: fs.bl

OpenFileMode

OpenFileMode :: enum {
    READ;
    WRITE;
    APPEND;
    CREATE;
}

Specify operation with opened file.

Variants

File: fs.bl

open_file

open_file :: fn (filepath: string_view, mode : OpenFileMode: OpenFileMode.READ) (_0: FileStream, _1: Error) #inline

Open an file specified by filepath. Function return file stream and OK status when file was opened, otherwise return invalid stream and proper error. Stream must be closed by close_file call.

File open mode is optional, any combination of OpenFileMode can be used. When Create mode is specified, new file is created on filepath only if it does not exist, otherwise already existing file is used. Read mode is used as default when neither Read, Write or Append is specified.

Example

#import "std/fs"
#import "std/print"
#import "std/io"
#import "std/string"

main :: fn () s32 {
	stream :: open_file(#file) catch {
		print_err($);
		return 1;
	};
	defer close_file(&stream);

	str: string;
	defer str_terminate(&str);

	read_bytes :: read_string(&stream, &str) catch {
		print_err($);
		return 2;
	};

	print("read % bytes\n", read_bytes);
	print("%\n", str);
	return 0;
}

File: fs.bl

close_file

close_file :: fn (stream: *FileStream)  #inline

Close previously openned file stream.

File: fs.bl

create_file

create_file :: fn (filepath: string_view) Error

Create new file if it does not exists. Otherwise does nothing.

File: fs.bl

remove_file

remove_file :: fn (filepath: string_view) Error #inline

Try to remove file specified by filepath and return OK on success, otherwise return error.

File: fs.bl

read_entire_file

read_entire_file :: fn (filepath: string_view, allocator : *Allocator: null) (_0: []u8, _1: Error)

Reads content of entire file on filepath into array of bytes. Allocator can be specified optionally, in case it's null default application context allocator will be used. Returned array might require explicit destruction by calling free_slice depenting on allocator being used. Use application_context.temporary_allocator in case the resulting content is not supposed to be persistent.

File: fs.bl

write_entire_file

write_entire_file :: fn (filepath: string_view, content: []u8, mode :: ) Error

Write entire content into the file on filepath.

File: fs.bl

copy_file

copy_file :: fn (src: string_view, dest: string_view, override :: false) Error #inline

Copy existing file from src to dest and override existing file in destination if override is true. Return ok or error.

The destination file is created if it does not exist.

Note: The src and dest path can be relative path to current working path set by set_cwd.

File: fs.bl

file_uid

file_uid :: fn { 
    fn (stream: *FileStream) (_0: u64, _1: Error); 
    _get_uid_by_name; 
}

Returns file id.

File: fs.bl

file_size

file_size :: fn (stream: *FileStream) (_0: s64, _1: Error)

Returns size in bytes of stream file or an error.

File: fs.bl

create_dir

create_dir :: fn (dirpath: string_view) Error #inline

Create new directory and return OK on success. This function does not create directories recursively.

File: fs.bl

create_all_dir

create_all_dir :: fn (dirpath: string_view) Error

File: fs.bl

remove_dir

remove_dir :: fn (dirpath: string_view) Error #inline

Remove directory specified by dirpath and return OK on success, otherwise return an error.

File: fs.bl

remove_all_dir

remove_all_dir :: fn { 
    impl_remove_all_dir; 
    impl_remove_all_dir_with_filter; 
    impl_remove_all_dir_with_filter_and_context; 
}

Remove (even non-empty) directory specified by dirpath and return OK on success, otherwise return an error. Root directory is removed if remove_root is true. Custom file filter function can be specified as needed.

Overloads:

fn (dirpath: string_view, remove_root := true) Error #inline
fn (dirpath: string_view, remove_root: bool, filter: *fn(info: *FileVisitInfo, ctx: *?T) bool, ctx: *T = null) Error

When the filter callback is specified, it's called for each visited file or directory. Returning true means the entry should be deleted.

Warning: When some files are excluded by the filter function the parent directory cannot be removed (it's not empty). Be careful excluding directories.

Note: This function recursively remove all nested folders and files in specified sub tree so it can be expensive.

File: fs.bl

FileVisitInfo

FileVisitInfo :: struct {
    is_directory: bool;
    filename: string_view;
    filepath: string_view;
    step_into_directory: bool;
}

Information about file entry.

Members

Note: Does not take any effect in case the leaf_first is set in visit options.

File: fs.bl

VisitOpt

VisitOpt :: struct {
    recursive: bool;
    leaf_first: bool;
}

Visit file options used in visit_files.

Members

File: fs.bl

visit_files

visit_files :: fn { 
    fn (dirpath: string_view, opt: VisitOpt, ctx: *?T, visitor: *fn (info: *FileVisitInfo, ctx: *T) Error) Error; 
    fn (dirpath: string_view, opt: VisitOpt, visitor: *fn (info: *FileVisitInfo) Error) Error; 
} #inline

Visit all files and directories in dirpath with specified visitor callback called for each found file entry. Optional context ctx pointer can be passed into the function.

Overloads:

fn (dirpath: string_view, opt: VisitOpt, ctx: *?T, visitor: *fn(info: *FileVisitInfo, ctx: *T) Error) Error #inline
fn (dirpath: string_view, opt: VisitOpt, visitor: *fn(info: *FileVisitInfo) Error) Error #inline

Example

#import "std/fs"
#import "std/print"
#import "std/string"
#import "std/array"

main :: fn () s32 {
	visitor :: fn (info: *FileVisitInfo, list: *[..]string) Error {
		if info.is_directory { return OK; }
		_, ext :: path_splitext(info.filename);
		if str_match(ext, ".bl") {
			array_push(list, str_make(info.filepath));
		}
		return OK;
	};

	list: [..]string;
	defer array_terminate(&list);
	cwd :: get_cwd();
	defer str_terminate(&cwd);
	err :: visit_files(cwd, VisitOpt.{ recursive = true }, &list, &visitor);
	if err { panic(err); }

	loop i := 0; i < list.len; i += 1 {
		print_log("FILE: %\n", list[i]);
		str_terminate(&list[i]);
	}

	return 0;
}

File: fs.bl

is_directory

is_directory :: fn (path: string_view) (_0: bool, _1: Error) #inline

Check whether path points to valid directory. Returns error in case the check failed.

File: fs.bl

validate_filename

validate_filename :: fn (name: string_view) bool #inline

Checks whether name is valid file name on current platform.

File: fs.bl

file_exist

file_exist :: fn (filepath: string_view) bool #inline

Check whether file or directory exists.

File: fs.bl

path_normalize

path_normalize :: fn (filepath: *string) Error #inline

Try to normalize filepath, basically try to remove all relative path nodes .. and .. Path must be valid path (existing) on system. Original filepath is extended with current working directory. Function return OK on success or proper error on fail. Original string is not modified when error occurs.

File: fs.bl

path_split

path_split :: fn (filepath: string_view) (head: string_view, tail: string_view)

Split input filepath into head and tail components. The tail is the last filepath component and the head is everything before. Only unix / path delimiters are supported. The tail component never contains path separators.

Example

filepath head tail
C:/foo/bar/file.txt C:/foo/bar/ file.txt
file.txt - file.txt
/usr/local/.hidden.file /usr/local/ .hidden.file
/ / -
C:/ C:/ -

File: fs.bl

path_splitext

path_splitext :: fn (filepath: string_view) (head: string_view, ext: string_view)

Split input filepath into head and ext components. The ext is the file extension and the head is everything before.

Example

filepath head ext
C:/foo/bar/file.txt C:/foo/bar/file .txt
file.txt file .txt
/usr/local/.hidden.file /usr/local/.hidden .file
/ / -
C:/ C:/ -

File: fs.bl

get_cwd

get_cwd :: fn () string #inline

Try to obtain current working directory, result must be released by str_terminate. Path does not contain last path separator.

File: fs.bl

set_cwd

set_cwd :: fn (path: string_view) Error #inline

Sets current working directory and return OK on success, otherwise return error.

File: fs.bl

get_home

get_home :: fn () string #inline

Try to obtain system home directory, result must be released by str_terminate. Path does not contain last path separator.

File: fs.bl

get_tmp

get_tmp :: fn () string #inline

Try to obtain system temporary directory, result must be released by str_terminate. Path does not contain last path separator.

File: fs.bl