Skip to content

Commit

Permalink
Exerc 8_2.
Browse files Browse the repository at this point in the history
  • Loading branch information
rsm-lisper committed Aug 3, 2024
1 parent e7421a8 commit 286ef48
Show file tree
Hide file tree
Showing 20 changed files with 439 additions and 0 deletions.
3 changes: 3 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BINARY=fopen_fields

include ../../Exercise.mk
86 changes: 86 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/knr_io.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <fcntl.h>
# include "knr_io.h"

KNR_FILE knr_iob[KNR_OPEN_MAX] = { /* stdin, stdout, stderr */
{ 0, (char *) 0, (char *) 0, 0, 1, 0, 0, 0, 0 },
{ 0, (char *) 0, (char *) 0, 1, 0, 1, 0, 0, 0 },
{ 0, (char *) 0, (char *) 0, 2, 0, 1, 1, 0, 0 }
};

/* knr_fopen: open file, return KNR_FILE* on success, KNR_NULL on error */
KNR_FILE *knr_fopen (char *name, char *mode)
{
int fd;
KNR_FILE *fp;

if (*mode != 'r' && *mode != 'w' && *mode != 'a')
return KNR_NULL;
for (fp = knr_iob; fp < knr_iob + KNR_OPEN_MAX; fp++)
if (fp->f_read == 0 && fp->f_write == 0)
break; /* found free slot */
if (fp >= knr_iob + KNR_OPEN_MAX) /* no free slots */
return KNR_NULL;

if (*mode == 'w')
fd = creat(name, KNR_PERMS);
else if (*mode == 'a') {
if ((fd = open(name, O_WRONLY, 0)) == -1)
fd = creat(name, KNR_PERMS);
lseek(fd, 0L, 2);
} else
fd = open(name, O_RDONLY, 0);
if (fd == -1) /* couldn't access name */
return KNR_NULL;
fp->fd = fd;
fp->cnt = 0;
fp->base = KNR_NULL;
if (*mode == 'r')
fp->f_read = 1;
else
fp->f_write = 1;
return fp;
}

/* knr_fillbuf: allocate and fill input buffer */
int knr_fillbuf (KNR_FILE *fp)
{
int bufsize;

if (fp->f_read == 0 || fp->f_eof == 1 || fp->f_err == 1)
return KNR_EOF;
bufsize = fp->f_unbuf==1 ? 1 : KNR_BUFSIZ;
if (fp->base == KNR_NULL) /* no buffer yet */
if ((fp->base = (char*) malloc(bufsize)) == NULL)
return KNR_EOF; /* can't get buffer */
fp->ptr = fp->base;
fp->cnt = read(fp->fd, fp->ptr, bufsize);
if (--fp->cnt < 0) {
if (fp->cnt == -1)
fp->f_eof = 1;
else
fp->f_err = 1;
fp->cnt = 0;
return KNR_EOF;
}
return (unsigned char) *fp->ptr++;
}

/* knr_flushbuf: flush buffer (TODO LATER) */
int knr_flushbuf (int, KNR_FILE *)
{
return 0;
}

/* knr_fclose: close a stream, return 0 on success, KNR_EOF on error */
int knr_fclose (KNR_FILE *fp)
{
int r;

if ((r = close(fp->fd)) == -1)
return KNR_EOF;
fp->f_read = fp->f_write = fp->f_unbuf = fp->f_eof = fp->f_err = 0;
return 0;
}
47 changes: 47 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/knr_io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ifndef KNR_IO_H
# define KNR_IO_H

# define KNR_PERMS 0666 /* RW for owner, group, others */

# define KNR_NULL 0
# define KNR_EOF (-1)
# define KNR_BUFSIZ 1024
# define KNR_OPEN_MAX 20 /* max #files open at once */

typedef struct knr_iobuf {
int cnt; /* characters left */
char *ptr; /* next character position */
char *base; /* location of buffer */
int fd; /* file descriptor */
/* mode of file access: */
int f_read; /* file open for reading */
int f_write; /* file open for writing */
int f_unbuf; /* file is unbuffered */
int f_eof; /* EOF has occurred on this file */
int f_err; /* error occurred on this file */
} KNR_FILE;
extern KNR_FILE knr_iob[KNR_OPEN_MAX];

# define knr_stdin (&knr_iob[0])
# define knr_stdout (&knr_iob[1])
# define knr_stderr (&knr_iob[2])

/* knr_fopen: open file, return KNR_FILE* on success, KNR_NULL on error */
KNR_FILE *knr_fopen (char *name, char *mode);
/* knr_fillbuf: allocate and fill input buffer */
int knr_fillbuf (KNR_FILE *fp);
/* knr_flushbuf: flush buffer */
int knr_flushbuf (int, KNR_FILE *);
/* knr_fclose: close a stream, return 0 on success, KNR_EOF on error */
int knr_fclose (KNR_FILE *fp);

# define knr_feof(p) ((p)->flag & KNR_EOF) != 0)
# define knr_ferror(p) ((p)->flag & KNR_ERR) != 0)
# define knr_fileno(p) ((p)->fd)

# define knr_getc(p) (--(p)->cnt >= 0 ? (unsigned char) *(p)->ptr++ : knr_fillbuf(p))
# define knr_putc(x,p) (--(p)->cnt >= 0 ? *(p)->ptr++ = (x) : knr_flushbuf((x),p))
# define knr_getchar() knr_getc(knr_stdin)
# define knr_putchar(x) knr_putc((x), knr_stdout)

# endif
24 changes: 24 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# include <stdio.h>
# include <error.h>
# include "knr_io.h"


int main (int argc, char *argv[])
{
KNR_FILE *fp;
int c;

if (argc == 1)
printf("Usage: %s <file1> <...fileN>\n", argv[0]);
else
while (--argc > 0) {
if ((fp = knr_fopen(*++argv, "r")) == KNR_NULL)
error(1, 0, "Can't open file %s.", *argv);
while ((c = knr_getc(fp)) != KNR_EOF)
putchar(c);
if (knr_fclose(fp) != 0)
error(2, 0, "Can't close file %s.", *argv);
}

return 0;
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Usage: ./fopen_fields <file1> <...fileN>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
no_such_file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
./fopen_fields: Can't open file no_such_file.txt.
Empty file.
Empty file.
24 changes: 24 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/tests/2_file.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# include <stdio.h>
# include <error.h>
# include "knr_io.h"


int main (int argc, char *argv[])
{
KNR_FILE *fp;
int c;

if (argc == 1)
printf("Usage: %s <file1> <...fileN>\n", argv[0]);
else
while (--argc > 0) {
if ((fp = knr_fopen(*++argv, "r")) == KNR_NULL)
error(1, 0, "Can't open file %s.", *argv);
while ((c = knr_getc(fp)) != KNR_EOF)
putchar(c);
if (knr_fclose(fp) != 0)
error(2, 0, "Can't close file %s.", *argv);
}

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/2_file.c
Empty file.
24 changes: 24 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/tests/2_one.tout
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# include <stdio.h>
# include <error.h>
# include "knr_io.h"


int main (int argc, char *argv[])
{
KNR_FILE *fp;
int c;

if (argc == 1)
printf("Usage: %s <file1> <...fileN>\n", argv[0]);
else
while (--argc > 0) {
if ((fp = knr_fopen(*++argv, "r")) == KNR_NULL)
error(1, 0, "Can't open file %s.", *argv);
while ((c = knr_getc(fp)) != KNR_EOF)
putchar(c);
if (knr_fclose(fp) != 0)
error(2, 0, "Can't close file %s.", *argv);
}

return 0;
}
24 changes: 24 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/tests/3_file0.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# include <stdio.h>
# include <error.h>
# include "knr_io.h"


int main (int argc, char *argv[])
{
KNR_FILE *fp;
int c;

if (argc == 1)
printf("Usage: %s <file1> <...fileN>\n", argv[0]);
else
while (--argc > 0) {
if ((fp = knr_fopen(*++argv, "r")) == KNR_NULL)
error(1, 0, "Can't open file %s.", *argv);
while ((c = knr_getc(fp)) != KNR_EOF)
putchar(c);
if (knr_fclose(fp) != 0)
error(2, 0, "Can't close file %s.", *argv);
}

return 0;
}
86 changes: 86 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/tests/3_file1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <fcntl.h>
# include "knr_io.h"

KNR_FILE knr_iob[KNR_OPEN_MAX] = { /* stdin, stdout, stderr */
{ 0, (char *) 0, (char *) 0, 0, 1, 0, 0, 0, 0 },
{ 0, (char *) 0, (char *) 0, 1, 0, 1, 0, 0, 0 },
{ 0, (char *) 0, (char *) 0, 2, 0, 1, 1, 0, 0 }
};

/* knr_fopen: open file, return KNR_FILE* on success, KNR_NULL on error */
KNR_FILE *knr_fopen (char *name, char *mode)
{
int fd;
KNR_FILE *fp;

if (*mode != 'r' && *mode != 'w' && *mode != 'a')
return KNR_NULL;
for (fp = knr_iob; fp < knr_iob + KNR_OPEN_MAX; fp++)
if (fp->f_read == 0 && fp->f_write == 0)
break; /* found free slot */
if (fp >= knr_iob + KNR_OPEN_MAX) /* no free slots */
return KNR_NULL;

if (*mode == 'w')
fd = creat(name, KNR_PERMS);
else if (*mode == 'a') {
if ((fd = open(name, O_WRONLY, 0)) == -1)
fd = creat(name, KNR_PERMS);
lseek(fd, 0L, 2);
} else
fd = open(name, O_RDONLY, 0);
if (fd == -1) /* couldn't access name */
return KNR_NULL;
fp->fd = fd;
fp->cnt = 0;
fp->base = KNR_NULL;
if (*mode == 'r')
fp->f_read = 1;
else
fp->f_write = 1;
return fp;
}

/* knr_fillbuf: allocate and fill input buffer */
int knr_fillbuf (KNR_FILE *fp)
{
int bufsize;

if (fp->f_read == 0 || fp->f_eof == 1 || fp->f_err == 1)
return KNR_EOF;
bufsize = fp->f_unbuf==1 ? 1 : KNR_BUFSIZ;
if (fp->base == KNR_NULL) /* no buffer yet */
if ((fp->base = (char*) malloc(bufsize)) == NULL)
return KNR_EOF; /* can't get buffer */
fp->ptr = fp->base;
fp->cnt = read(fp->fd, fp->ptr, bufsize);
if (--fp->cnt < 0) {
if (fp->cnt == -1)
fp->f_eof = 1;
else
fp->f_err = 1;
fp->cnt = 0;
return KNR_EOF;
}
return (unsigned char) *fp->ptr++;
}

/* knr_flushbuf: flush buffer (TODO LATER) */
int knr_flushbuf (int, KNR_FILE *)
{
return 0;
}

/* knr_fclose: close a stream, return 0 on success, KNR_EOF on error */
int knr_fclose (KNR_FILE *fp)
{
int r;

if ((r = close(fp->fd)) == -1)
return KNR_EOF;
fp->f_read = fp->f_write = fp->f_unbuf = fp->f_eof = fp->f_err = 0;
return 0;
}
3 changes: 3 additions & 0 deletions chapter_8.unix_interface/8_2.fopen_fields/tests/3_file2.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BINARY=fopen_fields

include ../../Exercise.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/3_file0.c tests/3_file1.c tests/3_file2.mk
Empty file.
Loading

0 comments on commit 286ef48

Please sign in to comment.