file_stream.c
2.78 KB
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
121
122
123
124
125
126
/* GNU mailutils - a suite of utilities for electronic mail
Copyright (C) 1999, 2000 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Library Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io0.h>
struct _file_stream
{
FILE *file;
int offset;
};
static void
_file_destroy (stream_t stream)
{
struct _file_stream *fs = stream->owner;
if (fs->file)
fclose (fs->file);
free (fs);
}
static int
_file_read (stream_t stream, char *optr, size_t osize,
off_t offset, size_t *nbytes)
{
struct _file_stream *fs = stream->owner;
if (fs->offset != offset)
{
fseek (fs->file, offset, SEEK_SET);
fs->offset = offset;
}
*nbytes = fread (optr, osize, 1, fs->file);
if (*nbytes == 0)
{
if (ferror(fs->file))
return errno;
}
else
fs->offset += *nbytes;
return 0;
}
static int
_file_write (stream_t stream, const char *iptr, size_t isize,
off_t offset, size_t *nbytes)
{
struct _file_stream *fs = stream->owner;
if (fs->offset != offset)
{
fseek (fs->file, offset, SEEK_SET);
fs->offset = offset;
}
*nbytes = fwrite (iptr, isize, 1, fs->file);
if (*nbytes == 0)
{
if (ferror (fs->file))
return errno;
}
else
fs->offset += *nbytes;
return 0;
}
int
file_stream_create (stream_t *stream, const char *filename, int flags)
{
struct _file_stream *fs;
char *mode;
int ret;
if (stream == NULL || filename == NULL)
return EINVAL;
if ((fs = calloc(sizeof(struct _file_stream), 1)) == NULL)
return ENOMEM;
if (flags & MU_STREAM_RDWR)
mode = "r+b";
else if (flags & MU_STREAM_READ)
mode = "rb";
else if (flags & MU_STREAM_WRITE)
mode = "wb";
else
return EINVAL;
if ((fs->file = fopen (filename, mode)) == NULL)
{
ret = errno;
free (fs);
return ret;
}
if ((ret = stream_create (stream, flags, fs)) != 0)
{
fclose (fs->file);
free (fs);
return ret;
}
stream_set_read(*stream, _file_read, fs );
stream_set_write(*stream, _file_write, fs );
stream_set_destroy(*stream, _file_destroy, fs );
return 0;
}