-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
04035b9
commit 593a95d
Showing
20 changed files
with
491 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
BINARY=flush_cat | ||
|
||
include ../../Exercise.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
# include <stdio.h> | ||
# include <stdlib.h> | ||
# include <unistd.h> | ||
# include <fcntl.h> | ||
# include "knr_io.h" | ||
|
||
enum knr_flags { | ||
KNR_FREAD = 01, /* file open for reading */ | ||
KNR_FWRITE = 02, /* file open for writing */ | ||
KNR_FUNBUF = 04, /* file is unbuffered */ | ||
KNR_FEOF = 010, /* EOF has occurred on this file */ | ||
KNR_FERR = 020, /* error occurred on this file */ | ||
KNR_FWL = 030 /* wrote less then buffer size */ | ||
}; | ||
|
||
KNR_FILE knr_iob[KNR_OPEN_MAX] = { /* stdin, stdout, stderr */ | ||
{ 0, (char *) 0, (char *) 0, KNR_FREAD, 0 }, | ||
{ 0, (char *) 0, (char *) 0, KNR_FWRITE, 1 }, | ||
{ 0, (char *) 0, (char *) 0, KNR_FWRITE | KNR_FUNBUF, 2 } | ||
}; | ||
|
||
/* 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->flag & (KNR_FREAD | KNR_FWRITE)) == 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; | ||
fp->flag = (*mode == 'r') ? KNR_FREAD : KNR_FWRITE; | ||
return fp; | ||
} | ||
|
||
/* knr_fillbuf: allocate and fill input buffer */ | ||
int knr_fillbuf (KNR_FILE *fp) | ||
{ | ||
int bufsize; | ||
|
||
if ((fp->flag & (KNR_FREAD | KNR_FEOF | KNR_FERR)) != KNR_FREAD) | ||
return KNR_EOF; | ||
bufsize = (fp->flag & KNR_FUNBUF) ? 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->flag |= KNR_FEOF; | ||
else | ||
fp->flag |= KNR_FERR; | ||
fp->cnt = 0; | ||
return KNR_EOF; | ||
} | ||
return (unsigned char) *fp->ptr++; | ||
} | ||
|
||
/* knr_flushbuf: flush output buffer, store c, return c on success, KNR_FWL on error */ | ||
int knr_flushbuf (int c, KNR_FILE *fp) | ||
{ | ||
int bufsize; | ||
|
||
if ((fp->flag & (KNR_FWRITE | KNR_FEOF | KNR_FERR)) != KNR_FWRITE) | ||
return KNR_FWL; | ||
bufsize = (fp->flag & KNR_FUNBUF) ? 1 : KNR_BUFSIZ; | ||
if (fp->base == KNR_NULL) { /* no buffer yet */ | ||
if ((fp->base = (char*) malloc(bufsize)) == NULL) | ||
return KNR_FWL; | ||
} | ||
else { | ||
fp->cnt = write(fp->fd, fp->base, fp->ptr - fp->base); | ||
if (fp->cnt < fp->ptr - fp->base) { | ||
if (fp->cnt == -1) | ||
fp->flag |= KNR_FWL; | ||
fp->flag |= KNR_FERR; | ||
return KNR_FWL; | ||
} | ||
} | ||
fp->cnt = bufsize; | ||
fp->ptr = fp->base; | ||
fp->cnt -= 1; | ||
return *fp->ptr++ = c; | ||
} | ||
|
||
/* knr_fflush: flush output buffer, return 0 on success, KNR_FWL on error */ | ||
int knr_fflush (KNR_FILE *fp) | ||
{ | ||
int bufsize; | ||
|
||
if ((fp->flag & (KNR_FWRITE | KNR_FEOF | KNR_FERR)) != KNR_FWRITE) | ||
return KNR_FWL; | ||
bufsize = (fp->flag & KNR_FUNBUF) ? 1 : KNR_BUFSIZ; | ||
if (fp->base == KNR_NULL) /* no buffer yet */ | ||
return KNR_FWL; | ||
else { | ||
fp->cnt = write(fp->fd, fp->base, fp->ptr - fp->base); | ||
if (fp->cnt < fp->ptr - fp->base) { | ||
if (fp->cnt == -1) | ||
fp->flag |= KNR_FWL; | ||
fp->flag |= KNR_FERR; | ||
return KNR_FWL; | ||
} | ||
} | ||
fp->cnt = bufsize; | ||
fp->ptr = fp->base; | ||
return 0; | ||
} | ||
|
||
/* knr_fclose: close a stream, return 0 on success, KNR_EOF on error */ | ||
int knr_fclose (KNR_FILE *fp) | ||
{ | ||
if ((fp->flag & (KNR_FWRITE | KNR_FEOF | KNR_FERR)) == KNR_FWRITE) | ||
if (knr_fflush(fp) != 0) | ||
return KNR_EOF; | ||
if (close(fp->fd) == -1) | ||
return KNR_EOF; | ||
free(fp->base); | ||
fp->flag = 0; | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# 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 128 | ||
# 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 flag; /* mode of file access */ | ||
int fd; /* file descriptor */ | ||
} 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 output buffer, store c, return c on success, KNR_FWL on error */ | ||
int knr_flushbuf (int c, KNR_FILE *fp); | ||
/* knr_fflush: flush output buffer, return 0 on success, KNR_FWL on error */ | ||
int knr_fflush (KNR_FILE *fp); | ||
/* 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# 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) | ||
knr_putchar(c); | ||
if (knr_fclose(fp) != 0) | ||
error(2, 0, "Can't close file %s.", *argv); | ||
} | ||
knr_fflush(knr_stdout); | ||
knr_fflush(knr_stderr); | ||
|
||
return 0; | ||
} |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Usage: ./flush_cat <file1> <...fileN> |
1 change: 1 addition & 0 deletions
1
chapter_8.unix_interface/8_3.flush_cat/tests/1_err_file_open.targs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
no_such_file.txt |
1 change: 1 addition & 0 deletions
1
chapter_8.unix_interface/8_3.flush_cat/tests/1_err_file_open.terr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
./flush_cat: Can't open file no_such_file.txt. |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
tests/2_file.c |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
BINARY=fopen_fields | ||
|
||
include ../../Exercise.mk |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
Oops, something went wrong.