libc: Implement the start of a FILE* API (the standard, portable C way of doing file stuff)
This commit is contained in:
parent
9e0bd39964
commit
93f6be9319
@ -1,4 +1,4 @@
|
|||||||
#include <fcntl.h>
|
#include <errno.h>
|
||||||
#include <luna.h>
|
#include <luna.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -32,19 +32,21 @@ int main()
|
|||||||
|
|
||||||
printf("Opening %s for reading...\n", filename);
|
printf("Opening %s for reading...\n", filename);
|
||||||
|
|
||||||
int fd = open(filename, O_RDONLY);
|
FILE* config = fopen(filename, "r");
|
||||||
if (fd < 0)
|
if (!config)
|
||||||
{
|
{
|
||||||
perror("open");
|
perror("fopen");
|
||||||
// return 1;
|
// return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char buf[4096];
|
char buf[4096];
|
||||||
|
|
||||||
ssize_t nread = read(fd, buf, sizeof(buf));
|
size_t nread = fread(buf, sizeof(buf), 1, config);
|
||||||
if (nread < 0)
|
if (nread == 0 && errno != 0) // FIXME: looks like our only way of checking whether a zero-read is an error or eof
|
||||||
|
// right now is checking errno, since fread() does not differentiate between the two,
|
||||||
|
// and feof() and ferror() are not yet implemented
|
||||||
{
|
{
|
||||||
perror("read");
|
perror("fread");
|
||||||
// return 1;
|
// return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -56,9 +58,9 @@ int main()
|
|||||||
printf("%s", buf);
|
printf("%s", buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close(fd) < 0)
|
if (fclose(config) < 0)
|
||||||
{
|
{
|
||||||
perror("close");
|
perror("fclose");
|
||||||
// return 1;
|
// return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
errno = (int)(-rc); \
|
errno = (int)(-rc); \
|
||||||
return -1; \
|
return -1; \
|
||||||
} \
|
} \
|
||||||
|
errno = 0; \
|
||||||
return (type)rc; \
|
return (type)rc; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@ -20,6 +21,7 @@
|
|||||||
errno = (int)((rc)&0xff); \
|
errno = (int)((rc)&0xff); \
|
||||||
return (type)-1; \
|
return (type)-1; \
|
||||||
} \
|
} \
|
||||||
|
errno = 0; \
|
||||||
return (type)rc; \
|
return (type)rc; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
int unused;
|
int fd;
|
||||||
} FILE;
|
} FILE;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
61
libs/libc/src/file.cpp
Normal file
61
libs/libc/src/file.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <luna.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
int fclose(FILE* stream)
|
||||||
|
{
|
||||||
|
int status = close(stream->fd);
|
||||||
|
free(stream); // We do not want to leak memory. man fclose(3) says that whether fclose() fails or not, any
|
||||||
|
// further operation on the stream results in undefined behavior. So we are free to free the
|
||||||
|
// stream.
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fflush(FILE*)
|
||||||
|
{
|
||||||
|
return 0; // FIXME: Implement buffered IO.
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* fopen(const char* pathname, const char*)
|
||||||
|
{
|
||||||
|
int fd = open(pathname, O_RDONLY); // FIXME: Use the mode string.
|
||||||
|
if (fd < 0) { return 0; }
|
||||||
|
FILE* stream = (FILE*)malloc(sizeof(FILE));
|
||||||
|
stream->fd = fd;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fread(void* buf, size_t size, size_t nmemb, FILE* stream)
|
||||||
|
{
|
||||||
|
ssize_t status = read(stream->fd, buf, size * nmemb);
|
||||||
|
if (status < 0)
|
||||||
|
return 0; // FIXME: The manual says that fread() does not differentiate between EOF and error, and that
|
||||||
|
// ferror() and feof() should be called to determine such. So right now, we just mask the error,
|
||||||
|
// until that is implemented.
|
||||||
|
return (size_t)status;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fseek(FILE*, long, int)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED("fseek");
|
||||||
|
}
|
||||||
|
|
||||||
|
long ftell(FILE*)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED("ftell");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fwrite(const void*, size_t, size_t, FILE*)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED("fwrite");
|
||||||
|
}
|
||||||
|
|
||||||
|
void setbuf(FILE*, char*)
|
||||||
|
{
|
||||||
|
NOT_IMPLEMENTED("setbuf");
|
||||||
|
}
|
||||||
|
}
|
@ -329,4 +329,46 @@ extern "C"
|
|||||||
},
|
},
|
||||||
max == 0 ? 0 : max - 1, ap);
|
max == 0 ? 0 : max - 1, ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int snprintf(char* str, size_t max, const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int written = vsnprintf(str, max, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sprintf(char* str, const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int written = vsprintf(str, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
int printf(const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int written = vprintf(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fprintf(FILE*, const char* format, ...) // FIXME: Make fprintf print to the selected file instead of stdout.
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
int written = vprintf(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
int vfprintf(FILE*, const char* format,
|
||||||
|
va_list ap) // FIXME: Make vfprintf print to the selected file instead of stdout.
|
||||||
|
{
|
||||||
|
return vprintf(format, ap);
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,51 +8,6 @@
|
|||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
int fclose(FILE*)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("fclose");
|
|
||||||
}
|
|
||||||
int fflush(FILE*)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("fflush");
|
|
||||||
}
|
|
||||||
FILE* fopen(const char*, const char*)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("fopen");
|
|
||||||
}
|
|
||||||
int fprintf(FILE*, const char* format, ...) // FIXME: Make fprintf print to the selected file instead of stdout.
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
int written = vprintf(format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
size_t fread(void*, size_t, size_t, FILE*)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("fread");
|
|
||||||
}
|
|
||||||
int fseek(FILE*, long, int)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("fseek");
|
|
||||||
}
|
|
||||||
long ftell(FILE*)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("ftell");
|
|
||||||
}
|
|
||||||
size_t fwrite(const void*, size_t, size_t, FILE*)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("fwrite");
|
|
||||||
}
|
|
||||||
void setbuf(FILE*, char*)
|
|
||||||
{
|
|
||||||
NOT_IMPLEMENTED("setbuf");
|
|
||||||
}
|
|
||||||
int vfprintf(FILE*, const char* format,
|
|
||||||
va_list ap) // FIXME: Make vfprintf print to the selected file instead of stdout.
|
|
||||||
{
|
|
||||||
return vprintf(format, ap);
|
|
||||||
}
|
|
||||||
int puts(const char* s)
|
int puts(const char* s)
|
||||||
{
|
{
|
||||||
long nwritten = syscall(SYS_write, s, strlen(s));
|
long nwritten = syscall(SYS_write, s, strlen(s));
|
||||||
@ -60,33 +15,11 @@ extern "C"
|
|||||||
nwritten += syscall(SYS_write, "\n", 1);
|
nwritten += syscall(SYS_write, "\n", 1);
|
||||||
return (int)nwritten;
|
return (int)nwritten;
|
||||||
}
|
}
|
||||||
int snprintf(char* str, size_t max, const char* format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
int written = vsnprintf(str, max, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
int sprintf(char* str, const char* format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
int written = vsprintf(str, format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
int printf(const char* format, ...)
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, format);
|
|
||||||
int written = vprintf(format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
return written;
|
|
||||||
}
|
|
||||||
void perror(const char* s) // FIXME: Print to stderr, whenever we have an stderr.
|
void perror(const char* s) // FIXME: Print to stderr, whenever we have an stderr.
|
||||||
{
|
{
|
||||||
|
int savederr =
|
||||||
|
errno; // This was necessary before, but even more now since we clear errno on successful syscalls now.
|
||||||
if (s && *s) { printf("%s: ", s); }
|
if (s && *s) { printf("%s: ", s); }
|
||||||
printf("%s\n", strerror(errno));
|
printf("%s\n", strerror(savederr));
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user