mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
fs: basic filesystem support over BFile
This commit is contained in:
parent
71de4dcb95
commit
8635880bbb
12 changed files with 390 additions and 0 deletions
|
@ -22,18 +22,34 @@ endif()
|
||||||
configure_file(include/gint/config.h.in include/gint/config.h)
|
configure_file(include/gint/config.h.in include/gint/config.h)
|
||||||
|
|
||||||
set(SOURCES_COMMON
|
set(SOURCES_COMMON
|
||||||
|
# Clock Pulse Generator driver
|
||||||
src/cpg/cpg.c
|
src/cpg/cpg.c
|
||||||
|
# CPU driver
|
||||||
src/cpu/atomic.c
|
src/cpu/atomic.c
|
||||||
src/cpu/cpu.c
|
src/cpu/cpu.c
|
||||||
src/cpu/ics.s
|
src/cpu/ics.s
|
||||||
src/cpu/registers.s
|
src/cpu/registers.s
|
||||||
src/cpu/sleep.c
|
src/cpu/sleep.c
|
||||||
|
# Direct Memory Access driver
|
||||||
src/dma/dma.c
|
src/dma/dma.c
|
||||||
src/dma/inth.s
|
src/dma/inth.s
|
||||||
src/dma/memcpy.c
|
src/dma/memcpy.c
|
||||||
src/dma/memset.c
|
src/dma/memset.c
|
||||||
|
# Filesystem interface (Fugue only)
|
||||||
|
src/fs/close.c
|
||||||
|
src/fs/creat.c
|
||||||
|
src/fs/lseek.c
|
||||||
|
src/fs/open.c
|
||||||
|
src/fs/pread.c
|
||||||
|
src/fs/pwrite.c
|
||||||
|
src/fs/read.c
|
||||||
|
src/fs/unlink.c
|
||||||
|
src/fs/util.c
|
||||||
|
src/fs/write.c
|
||||||
|
# Interrupt Controller driver
|
||||||
src/intc/intc.c
|
src/intc/intc.c
|
||||||
src/intc/inth.s
|
src/intc/inth.s
|
||||||
|
# Kernel
|
||||||
src/kernel/exch.c
|
src/kernel/exch.c
|
||||||
src/kernel/exch.s
|
src/kernel/exch.s
|
||||||
src/kernel/hardware.c
|
src/kernel/hardware.c
|
||||||
|
@ -44,15 +60,19 @@ set(SOURCES_COMMON
|
||||||
src/kernel/syscalls.S
|
src/kernel/syscalls.S
|
||||||
src/kernel/tlbh.S
|
src/kernel/tlbh.S
|
||||||
src/kernel/world.c
|
src/kernel/world.c
|
||||||
|
# Key Scan Interface driver
|
||||||
src/keysc/getkey.c
|
src/keysc/getkey.c
|
||||||
src/keysc/iokbd.c
|
src/keysc/iokbd.c
|
||||||
src/keysc/keycodes.c
|
src/keysc/keycodes.c
|
||||||
src/keysc/keydev.c
|
src/keysc/keydev.c
|
||||||
src/keysc/keysc.c
|
src/keysc/keysc.c
|
||||||
|
# Memory allocator
|
||||||
src/kmalloc/arena_gint.c
|
src/kmalloc/arena_gint.c
|
||||||
src/kmalloc/arena_osheap.c
|
src/kmalloc/arena_osheap.c
|
||||||
src/kmalloc/kmalloc.c
|
src/kmalloc/kmalloc.c
|
||||||
|
# MMU driver
|
||||||
src/mmu/mmu.c
|
src/mmu/mmu.c
|
||||||
|
# Rendering
|
||||||
src/render/dhline.c
|
src/render/dhline.c
|
||||||
src/render/dimage.c
|
src/render/dimage.c
|
||||||
src/render/dline.c
|
src/render/dline.c
|
||||||
|
@ -62,13 +82,17 @@ set(SOURCES_COMMON
|
||||||
src/render/dupdate_hook.c
|
src/render/dupdate_hook.c
|
||||||
src/render/dvline.c
|
src/render/dvline.c
|
||||||
src/render/topti.c
|
src/render/topti.c
|
||||||
|
# RTC driver
|
||||||
src/rtc/rtc.c
|
src/rtc/rtc.c
|
||||||
src/rtc/rtc_ticks.c
|
src/rtc/rtc_ticks.c
|
||||||
|
# Sound Processing Unit driver
|
||||||
src/spu/spu.c
|
src/spu/spu.c
|
||||||
|
# Timer Unit driver
|
||||||
src/tmu/inth-etmu.s
|
src/tmu/inth-etmu.s
|
||||||
src/tmu/inth-tmu.s
|
src/tmu/inth-tmu.s
|
||||||
src/tmu/sleep.c
|
src/tmu/sleep.c
|
||||||
src/tmu/tmu.c
|
src/tmu/tmu.c
|
||||||
|
# USB driver
|
||||||
src/usb/classes/ff-bulk.c
|
src/usb/classes/ff-bulk.c
|
||||||
src/usb/configure.c
|
src/usb/configure.c
|
||||||
src/usb/pipes.c
|
src/usb/pipes.c
|
||||||
|
@ -77,6 +101,7 @@ set(SOURCES_COMMON
|
||||||
src/usb/usb.c
|
src/usb/usb.c
|
||||||
)
|
)
|
||||||
set(SOURCES_FX
|
set(SOURCES_FX
|
||||||
|
# Gray engine
|
||||||
src/gray/engine.c
|
src/gray/engine.c
|
||||||
src/gray/gclear.c
|
src/gray/gclear.c
|
||||||
src/gray/gint_gline.c
|
src/gray/gint_gline.c
|
||||||
|
@ -84,6 +109,7 @@ set(SOURCES_FX
|
||||||
src/gray/grect.c
|
src/gray/grect.c
|
||||||
src/gray/gsubimage.c
|
src/gray/gsubimage.c
|
||||||
src/gray/gtext.c
|
src/gray/gtext.c
|
||||||
|
# Rendering
|
||||||
src/render-fx/bopti-asm-gray-scsp.s
|
src/render-fx/bopti-asm-gray-scsp.s
|
||||||
src/render-fx/bopti-asm-gray.s
|
src/render-fx/bopti-asm-gray.s
|
||||||
src/render-fx/bopti-asm-mono-scsp.s
|
src/render-fx/bopti-asm-mono-scsp.s
|
||||||
|
@ -98,11 +124,15 @@ set(SOURCES_FX
|
||||||
src/render-fx/masks.c
|
src/render-fx/masks.c
|
||||||
src/render-fx/topti-asm.s
|
src/render-fx/topti-asm.s
|
||||||
src/render-fx/topti.c
|
src/render-fx/topti.c
|
||||||
|
# T6K11 driver
|
||||||
src/t6k11/t6k11.c
|
src/t6k11/t6k11.c
|
||||||
|
|
||||||
src/usb/classes/ff-bulk-gray.c
|
src/usb/classes/ff-bulk-gray.c
|
||||||
)
|
)
|
||||||
set(SOURCES_CG
|
set(SOURCES_CG
|
||||||
|
# R61524 driver
|
||||||
src/r61524/r61524.c
|
src/r61524/r61524.c
|
||||||
|
# Rendering
|
||||||
src/render-cg/bopti-asm.s
|
src/render-cg/bopti-asm.s
|
||||||
src/render-cg/bopti.c
|
src/render-cg/bopti.c
|
||||||
src/render-cg/dclear.c
|
src/render-cg/dclear.c
|
||||||
|
|
14
src/fs/close.c
Normal file
14
src/fs/close.c
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
int close(int fd)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE(-1);
|
||||||
|
|
||||||
|
int err = BFile_Close(fd);
|
||||||
|
if(err < 0) {
|
||||||
|
errno = bfile_error_to_errno(err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
6
src/fs/creat.c
Normal file
6
src/fs/creat.c
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
int creat(char const *path, mode_t mode)
|
||||||
|
{
|
||||||
|
return open(path, O_CREAT | O_WRONLY | O_TRUNC, mode);
|
||||||
|
}
|
37
src/fs/lseek.c
Normal file
37
src/fs/lseek.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
off_t lseek(int fd, off_t offset, int whence)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE((off_t)-1);
|
||||||
|
|
||||||
|
if(whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return (off_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On Graph 35+E II, there is no documented way to know the offset. */
|
||||||
|
if(gint[HWCALC] == HWCALC_G35PE2 && whence == SEEK_CUR) {
|
||||||
|
errno = ENOTSUP;
|
||||||
|
return (off_t)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t destination;
|
||||||
|
if(whence == SEEK_SET)
|
||||||
|
destination = offset;
|
||||||
|
else if(whence == SEEK_CUR)
|
||||||
|
destination = BFile_GetPos(fd) + offset;
|
||||||
|
else if(whence == SEEK_END)
|
||||||
|
destination = BFile_Size(fd) - offset;
|
||||||
|
|
||||||
|
int rc = BFile_Seek(fd, destination);
|
||||||
|
|
||||||
|
if(rc < 0) {
|
||||||
|
errno = bfile_error_to_errno(rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* rc is the amount of space left in the file (including pre-allocated
|
||||||
|
space), so instead just return destination directly */
|
||||||
|
return (off_t)destination;
|
||||||
|
}
|
74
src/fs/open.c
Normal file
74
src/fs/open.c
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
int open(char const *path, int flags, ...)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE(-1);
|
||||||
|
|
||||||
|
uint16_t *fcpath = utf8_to_fc_alloc(path, u"\\\\fls0\\");
|
||||||
|
int fd, err, rc = -1;
|
||||||
|
|
||||||
|
if(!fcpath) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open mode */
|
||||||
|
int bfile_mode = BFile_ReadOnly;
|
||||||
|
if(flags & O_WRONLY)
|
||||||
|
bfile_mode = BFile_WriteOnly;
|
||||||
|
else if(flags & O_RDWR)
|
||||||
|
bfile_mode = BFile_ReadWrite;
|
||||||
|
|
||||||
|
/* Exclusive creation requires the file to be created by the call */
|
||||||
|
bool excl = (flags & O_EXCL) && (flags & O_CREAT);
|
||||||
|
/* Truncation requires the file to be removed/recreated */
|
||||||
|
bool trunc = (flags & O_TRUNC) && (flags & O_CREAT);
|
||||||
|
|
||||||
|
/* Try and open the file normally, unless O_TRUNC is specified without
|
||||||
|
O_EXCL, in which case we simply delete and recreate the file. */
|
||||||
|
fd = BFile_EntryNotFound;
|
||||||
|
if(excl || !trunc)
|
||||||
|
fd = BFile_Open(fcpath, bfile_mode);
|
||||||
|
|
||||||
|
/* If the file exists and O_EXCL was requested, fail. */
|
||||||
|
if(fd >= 0 && excl) {
|
||||||
|
BFile_Close(fd);
|
||||||
|
errno = EEXIST;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If O_TRUNC is requested and either the file exists or O_CREAT is
|
||||||
|
set, temporarily remove it. */
|
||||||
|
if((flags & O_TRUNC) && (fd >= 0 || (flags & O_CREAT))) {
|
||||||
|
if(fd >= 0) BFile_Close(fd);
|
||||||
|
BFile_Remove(fcpath);
|
||||||
|
fd = BFile_EntryNotFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the file does not exist and O_CREAT is set, create it */
|
||||||
|
if((flags & O_CREAT) && ((flags & O_TRUNC) || fd < 0)) {
|
||||||
|
int size = 0;
|
||||||
|
err = BFile_Create(fcpath, BFile_File, &size);
|
||||||
|
if(err < 0) {
|
||||||
|
errno = bfile_error_to_errno(err);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
fd = BFile_Open(fcpath, bfile_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fd < 0) {
|
||||||
|
errno = bfile_error_to_errno(fd);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If O_APPEND is set, move to the end of the file */
|
||||||
|
if((flags & O_APPEND))
|
||||||
|
BFile_Seek(fd, BFile_Size(fd));
|
||||||
|
|
||||||
|
/* Return the now-open file descriptor */
|
||||||
|
rc = fd;
|
||||||
|
end:
|
||||||
|
free(fcpath);
|
||||||
|
return rc;
|
||||||
|
}
|
17
src/fs/pread.c
Normal file
17
src/fs/pread.c
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
ssize_t pread(int fd, void *buf, size_t size, off_t offset)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE(-1);
|
||||||
|
|
||||||
|
/* Thanks to the extra argument to BFile_Read(), we can perform this
|
||||||
|
call without knowing the current offset, even on G-III models */
|
||||||
|
int rc = BFile_Read(fd, buf, size, offset);
|
||||||
|
if(rc < 0) {
|
||||||
|
errno = bfile_error_to_errno(rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
BFile_Seek(fd, -size);
|
||||||
|
return rc;
|
||||||
|
}
|
28
src/fs/pwrite.c
Normal file
28
src/fs/pwrite.c
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
ssize_t pwrite(int fd, const void *buf, size_t size, off_t offset)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE((off_t)-1);
|
||||||
|
|
||||||
|
off_t current = lseek(fd, 0, SEEK_CUR);
|
||||||
|
|
||||||
|
if(current == (off_t)-1)
|
||||||
|
return (ssize_t)-1;
|
||||||
|
|
||||||
|
ssize_t rc = -1;
|
||||||
|
|
||||||
|
if(lseek(fd, 0, offset) == (off_t)-1)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
rc = BFile_Write(fd, buf, size);
|
||||||
|
if(rc < 0) {
|
||||||
|
errno = bfile_error_to_errno(rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
/* At the end, always try to restore the current position */
|
||||||
|
lseek(fd, current, SEEK_CUR);
|
||||||
|
return rc;
|
||||||
|
}
|
14
src/fs/read.c
Normal file
14
src/fs/read.c
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
ssize_t read(int fd, void *buf, size_t size)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE(-1);
|
||||||
|
|
||||||
|
int err = BFile_Read(fd, buf, size, -1);
|
||||||
|
if(err < 0) {
|
||||||
|
errno = bfile_error_to_errno(err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
21
src/fs/unlink.c
Normal file
21
src/fs/unlink.c
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
int unlink(char const *path)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE(-1);
|
||||||
|
|
||||||
|
uint16_t *fcpath = utf8_to_fc_alloc(path, u"\\\\fls0\\");
|
||||||
|
if(!fcpath) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int err = BFile_Remove(fcpath);
|
||||||
|
if(err < 0) {
|
||||||
|
errno = bfile_error_to_errno(err);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
94
src/fs/util.c
Normal file
94
src/fs/util.c
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#include "util.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int bfile_error_to_errno(int e)
|
||||||
|
{
|
||||||
|
/* TODO: Find BFile code for too many fds and map it to ENFILE. */
|
||||||
|
switch(e) {
|
||||||
|
case BFile_EntryNotFound: return ENOENT;
|
||||||
|
case BFile_IllegalPath: return EINVAL;
|
||||||
|
case BFile_DeviceFull: return EDQUOT;
|
||||||
|
case BFile_IllegalDevice: return EINVAL;
|
||||||
|
case BFile_AccessDenied: return EACCES;
|
||||||
|
case BFile_PermissionError: return EACCES;
|
||||||
|
case BFile_EntryFull: return EDQUOT;
|
||||||
|
case BFile_AlreadyExists: return EEXIST;
|
||||||
|
case BFile_ReadOnlyFile: return EACCES;
|
||||||
|
case BFile_EnumerateEnd: return ENOENT;
|
||||||
|
case BFile_IllegalSeekPos: return EINVAL;
|
||||||
|
case BFile_NotMountDevice: return ENOENT;
|
||||||
|
case BFile_DeviceNotFound: return ENOENT;
|
||||||
|
default: return errno;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Length of FONTCHARACTER and UTF-8 strings, counting only ASCII characters */
|
||||||
|
static size_t utf8_len(char const *utf8)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
for(size_t i = 0; utf8[i] != 0; i++)
|
||||||
|
len += (utf8[i] >= 0 && (uint8_t)utf8[i] <= 0x7f);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
static size_t fc_len(uint16_t const *fc)
|
||||||
|
{
|
||||||
|
size_t len = 0;
|
||||||
|
for(size_t i = 0; fc[i] != 0 && fc[i] != 0xffff; i++)
|
||||||
|
len += (fc[i] <= 0x7f);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void utf8_to_fc(uint16_t *fc, char const *utf8, size_t fc_len)
|
||||||
|
{
|
||||||
|
size_t j = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; j < fc_len && utf8[i] != 0; i++) {
|
||||||
|
if(utf8[i] >= 0 && (uint8_t)utf8[i] <= 0x7f)
|
||||||
|
fc[j++] = utf8[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while(j < fc_len)
|
||||||
|
fc[j++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fc_to_utf8(char *utf8, uint16_t const *fc, size_t utf8_len)
|
||||||
|
{
|
||||||
|
size_t j = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; j < utf8_len && fc[i] != 0 && fc[i] != 0xffff; i++) {
|
||||||
|
if(fc[i] <= 0x7f)
|
||||||
|
utf8[j++] = fc[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while(j < utf8_len)
|
||||||
|
utf8[j++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t *utf8_to_fc_alloc(char const *utf8, uint16_t *prefix)
|
||||||
|
{
|
||||||
|
size_t lenp = 0;
|
||||||
|
if(prefix) {
|
||||||
|
while(prefix[lenp] != 0 && prefix[lenp] != 0xffff)
|
||||||
|
lenp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t len = utf8_len(utf8);
|
||||||
|
uint16_t *fc = malloc((lenp+len+1) * sizeof *fc);
|
||||||
|
|
||||||
|
if(fc != NULL) {
|
||||||
|
if(prefix)
|
||||||
|
memcpy(fc, prefix, lenp * sizeof *prefix);
|
||||||
|
utf8_to_fc(fc + lenp, utf8, len+1);
|
||||||
|
}
|
||||||
|
return fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *fc_to_utf8_alloc(uint16_t const *fc)
|
||||||
|
{
|
||||||
|
size_t len = fc_len(fc);
|
||||||
|
char *utf8 = malloc(len+1);
|
||||||
|
if(utf8 != NULL)
|
||||||
|
fc_to_utf8(utf8, fc, len+1);
|
||||||
|
return utf8;
|
||||||
|
}
|
41
src/fs/util.h
Normal file
41
src/fs/util.h
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef FS_UTIL_H
|
||||||
|
#define FS_UTIL_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <bfile.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <gint/hardware.h>
|
||||||
|
|
||||||
|
#define ENOTSUP_IF_NOT_FUGUE(rc) \
|
||||||
|
if(gint[HWFS] != HWFS_FUGUE) { errno = ENOTSUP; return rc; }
|
||||||
|
|
||||||
|
/* Translate common BFile error codes to errno values. */
|
||||||
|
extern int bfile_error_to_errno(int bfile_error_code);
|
||||||
|
|
||||||
|
/* TODO: These functions do not actually translate special characters between
|
||||||
|
encodings, they simply strip them. */
|
||||||
|
|
||||||
|
/* Convert UTF-8 to FONTCHARACTER; outputs fc_len characters with padding. If
|
||||||
|
fc[fc_len-1] is not 0 after the call, then fc is too short. */
|
||||||
|
extern void utf8_to_fc(uint16_t *fc, char const *utf8, size_t fc_len);
|
||||||
|
|
||||||
|
/* Same in the other direction. */
|
||||||
|
extern void fc_to_utf8(char *utf8, uint16_t const *fc, size_t utf8_len);
|
||||||
|
|
||||||
|
/* Same as utf8_to_fc() but allocates a string with malloc(). */
|
||||||
|
extern uint16_t *utf8_to_fc_alloc(char const *utf8, uint16_t *prefix);
|
||||||
|
|
||||||
|
/* Same as fc_to_utf8() but allocates a string with malloc(). */
|
||||||
|
extern char *fc_to_utf8_alloc(uint16_t const *fc);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* FS_UTIL_H */
|
14
src/fs/write.c
Normal file
14
src/fs/write.c
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
ssize_t write(int fd, const void *buf, size_t size)
|
||||||
|
{
|
||||||
|
ENOTSUP_IF_NOT_FUGUE(-1);
|
||||||
|
|
||||||
|
int rc = BFile_Write(fd, buf, size);
|
||||||
|
if(rc < 0) {
|
||||||
|
errno = bfile_error_to_errno(rc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
Loading…
Reference in a new issue