Deadline: September 19th, 2014
For this assignment you must:
In this assignment, you may use the standard C functions malloc, realloc and free; as well as functions from previous assignments (by including their source in your submission). All other external functions are forbidden.
Each function to implement must be defined in its own .c file, named after the function. You must provide a suitable Makefile which compiles all the functions and places them in libminic.a.
You must implement the following functions:
int my_open(const char *path, int oflag, int mode); int my_close(int fd); long my_read(int fd, void *buf, unsigned long nbyte); long my_write(int fd, const void *buf, unsigned long nbyte);
Each function must contain inline assembly to perform a system call to the operating system. You must support at least one of the following combinations: Linux/i386, Linux/x86-64, FreeBSD/i386 or FreeBSD/amd64.
You can easily find information about the syscall interface of Linux and FreeBSD online. Some example links are provided in References below.
You must place their prototype in a header named mysys.h, together with suitable definitions for the preprocessor macros O_RDONLY, O_WRONLY, O_RDWR, O_CREAT, O_TRUNC.
NB: Checks for adherence to the C coding standard for the 4 source files containing the definition of these functions will be relaxed, in particular regarding compiler warnings. Ensure that you properly document violations using comments in your source code.
You must define your own type st_t in a header named mystream.h, based on a preprocessor macro ST_BUFFER_SIZE:
#ifndef MYSTREAM_H #define MYSTREAM_H #ifndef ST_BUFFER_SIZE #define ST_BUFFER_SIZE 8192 #endif typedef struct st { // Your definitions here... } st_t; // Functions declarations may follow here. #endif
You must then implement the following functions:
st_t *st_open(const char *, const char *); void st_close(st_t *); unsigned st_read(st_t *, void *, unsigned); unsigned st_write(st_t *, const void *, unsigned); void st_flush(st_t *); int st_gets(st_t *, char *, unsigned); int st_puts(st_t *, char *); int st_putchar(st_t *, int); int st_getchar(st_t *); char *st_getline(st_t *);
The purpose of this library is to implement buffered I/O:
You may implement the following for a higher grade:
lseek system call:
// Argument for whence: # define SEEK_SET 0 # define SEEK_CUR 1 # define SEEK_END 2 long my_lseek(int fd, long offset, int whence);
a valid preprocessor macro definition for O_APPEND in mysys.h;
the following additional libstream function:
long st_lseek(st_t *, long offset, int whence);
which calls my_lseek for the underlying file descriptor and handles buffering appropriately.
modes "a" and "a+" for st_open, which open the stream using modes “append-only” and “read/append”.
a global preprocessor macro called ERRNO that can be used to retrieve the most recent error, like errno in C.
Details about the syscall interfaces for Linux and FreeBSD:
System call numbers:
#if defined(__FreeBSD__)
# define O_RDONLY 0x0000
# define O_WRONLY 0x0001
# define O_RDWR 0x0002
# define O_APPEND 0x0008
# define O_CREAT 0x0200
# define O_TRUNC 0x0400
# define SYS_read 3
# define SYS_write 4
# define SYS_open 5
# define SYS_close 6
# define SYS_lseek 478
#elif defined(__linux__)
# define O_RDONLY 00
# define O_WRONLY 01
# define O_RDWR 02
# define O_CREAT 0100
# define O_TRUNC 01000
# define O_APPEND 02000
# if defined(__i386__)
# define SYS_read 3
# define SYS_write 4
# define SYS_open 5
# define SYS_close 6
# define SYS_lseek 19
# elif defined(__x86_64)
# define SYS_read 0
# define SYS_write 1
# define SYS_open 2
# define SYS_close 3
# define SYS_lseek 8
# endif
#endif