-
Notifications
You must be signed in to change notification settings - Fork 1
/
stream_file.c
executable file
·121 lines (97 loc) · 3.16 KB
/
stream_file.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "glknew.h"
static glui32 get_position(strid_t str) {
return lseek(str->u.file.fd, 0, SEEK_CUR);
}
static void set_position(strid_t str, glsi32 pos, glui32 seekmode) {
int fd = str->u.file.fd;
int whence;
if (seekmode == seekmode_Start) {
whence = SEEK_SET;
} else if (seekmode == seekmode_Current) {
whence = SEEK_CUR;
} else if (seekmode == seekmode_End) {
whence = SEEK_END;
} else {
printf("Can't happen: seekmode %d out of range\n", seekmode);
exit(~0);
}
if (lseek(fd, pos, whence) == -1) {
printf("Seek of fd %d to pos %d, whence=%d failed with errno=%d", fd, pos, whence, errno);
exit(~0);
}
}
static glsi32 get_char_uni(strid_t str) {
unsigned char ch;
ssize_t ret;
ret = read(str->u.file.fd, &ch, 1);
if (ret == 0) {
printf("DEBUG: get_char_uni(file) read returned %d, errno=%d, ch=0x%x\n",
ret, errno, ch);
return -1;
} else {
return ch & 0xFF;
}
}
static void file_put_char_uni(strid_t str, glui32 ch) {
ssize_t ret;
unsigned char real_ch;
if (ch > 255) {
printf("Over-wide character (U+%x) in put_char_uni for file stream\n", ch);
exit(26);
}
real_ch = (unsigned char)ch;
ret = write(str->u.file.fd, &real_ch, 1);
if (ret != 1) {
printf("Error writing to file, errno=%d\n", errno);
exit(27);
}
}
struct glk_stream_struct_vtable stream_file_vtable = {
.set_position = &set_position,
.get_position = &get_position,
.get_char_uni = &get_char_uni,
.put_char_uni = &file_put_char_uni,
};
/* This is probably woefully incomplete WRT unicode & textmode. */
strid_t glk_stream_open_file(frefid_t fileref, glui32 fmode,
glui32 rock) {
struct glk_stream_struct *stream = glk_stream_open_base(rock, fmode, STREAM_TYPE_FILE, &stream_file_vtable);
int fd;
int open_flags = 0;
char filemode_name[FILEMODE_NAME_LEN];
filemode_to_name(fmode, filemode_name);
printf("DEBUG: glk_stream_open_file, fileref->name=%s fmode=%d (%s)\n", fileref->name, fmode, filemode_name);
if (fmode == filemode_Write) {
open_flags |= O_CREAT | O_WRONLY;
} else if (fmode == filemode_Read) {
open_flags |= O_RDONLY;
} else {
printf("FIXME: fmode to open_flags\n");
exit(25);
}
/* rw for ugo. If the user doesn't like this, by all means, they
should set umask. */
fd = open(fileref->name, open_flags, 0666);
if (fd == -1) {
printf("DEBUG: open of file %s failed: errno=%d\n", fileref->name, errno);
return NULL;
}
stream->u.file.fd = fd;
return stream;
}
/* Not part of the glk API proper, but required by the glkunix API. */
/* Opens a given pathname, as a read-only stream. */
strid_t gli_stream_open_pathname(char *pathname, int textmode,
glui32 rock) {
frefid_t fileref;
strid_t stream;
glui32 fmode = filemode_Read;
fileref = glk_fileref_create_by_name(fileusage_Data | fileusage_BinaryMode, pathname, rock);
if (!fileref) {
printf("DEBUG: Couldn't create fileref for pathname %s in gli_stream_open_pathname\n", pathname);
exit(1);
}
stream = glk_stream_open_file(fileref, fmode, rock);
glk_fileref_destroy(fileref);
return stream;
}