]> mj.ucw.cz Git - libucw.git/blob - lib/fb-file.c
BCONFIG_CAN_OVERWRITE is a read/write parameter, i.e. the used can
[libucw.git] / lib / fb-file.c
1 /*
2  *      Sherlock Library -- Fast Buffered I/O on Files
3  *
4  *      (c) 1997--2002 Martin Mares <mj@ucw.cz>
5  *      (c) 2004 Robert Spalek <robert@ucw.cz>
6  *
7  *      This software may be freely distributed and used according to the terms
8  *      of the GNU Lesser General Public License.
9  */
10
11 #include "lib/lib.h"
12 #include "lib/fastbuf.h"
13 #include "lib/lfs.h"
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <fcntl.h>
18 #include <unistd.h>
19
20 struct fb_file {
21   struct fastbuf fb;
22   int fd;                               /* File descriptor, -1 if not a real file */
23   int is_temp_file;                     /* 0=normal file, 1=temporary file, delete on close, -1=shared FD */
24   int can_overwrite;
25 };
26 #define FB_FILE(f) ((struct fb_file *)(f)->is_fastbuf)
27
28 static int
29 bfd_refill(struct fastbuf *f)
30 {
31   int l = read(FB_FILE(f)->fd, f->buffer, f->bufend-f->buffer);
32   if (l < 0)
33     die("Error reading %s: %m", f->name);
34   f->bptr = f->buffer;
35   f->bstop = f->buffer + l;
36   f->pos += l;
37   return l;
38 }
39
40 static void
41 bfd_spout(struct fastbuf *f)
42 {
43   int l = f->bptr - f->buffer;
44   char *c = f->buffer;
45
46   f->pos += l;
47   while (l)
48     {
49       int z = write(FB_FILE(f)->fd, c, l);
50       if (z <= 0)
51         die("Error writing %s: %m", f->name);
52       l -= z;
53       c += z;
54     }
55   f->bptr = f->buffer;
56 }
57
58 static void
59 bfd_seek(struct fastbuf *f, sh_off_t pos, int whence)
60 {
61   sh_off_t l;
62
63   if (whence == SEEK_SET && pos == f->pos)
64     return;
65
66   l = sh_seek(FB_FILE(f)->fd, pos, whence);
67   if (l < 0)
68     die("lseek on %s: %m", f->name);
69   f->pos = l;
70 }
71
72 static void
73 bfd_close(struct fastbuf *f)
74 {
75   switch (FB_FILE(f)->is_temp_file)
76     {
77     case 1:
78       if (unlink(f->name) < 0)
79         log(L_ERROR, "unlink(%s): %m", f->name);
80     case 0:
81       close(FB_FILE(f)->fd);
82     }
83   xfree(f);
84 }
85
86 static int
87 bfd_config(struct fastbuf *f, uns item, int value)
88 {
89   switch (item)
90     {
91     case BCONFIG_IS_TEMP_FILE:
92       FB_FILE(f)->is_temp_file = value;
93       return 0;
94     case BCONFIG_CAN_OVERWRITE: ;
95       int old_value = FB_FILE(f)->can_overwrite;
96       if (value >= 0 && value <= 2)
97         FB_FILE(f)->can_overwrite = value;
98       return old_value;
99     default:
100       return -1;
101     }
102 }
103
104 static struct fastbuf *
105 bfdopen_internal(int fd, uns buflen, byte *name)
106 {
107   int namelen = strlen(name) + 1;
108   struct fb_file *F = xmalloc(sizeof(struct fb_file) + buflen + namelen);
109   struct fastbuf *f = &F->fb;
110
111   bzero(F, sizeof(*F));
112   f->buffer = (char *)(F+1);
113   f->bptr = f->bstop = f->buffer;
114   f->bufend = f->buffer + buflen;
115   f->name = f->bufend;
116   memcpy(f->name, name, namelen);
117   F->fd = fd;
118   f->refill = bfd_refill;
119   f->spout = bfd_spout;
120   f->seek = bfd_seek;
121   f->close = bfd_close;
122   f->config = bfd_config;
123   F->can_overwrite = 2;
124   return f;
125 }
126
127 struct fastbuf *
128 bopen(byte *name, uns mode, uns buffer)
129 {
130   struct fastbuf *b;
131   int fd;
132
133   if (!buffer)
134     return bopen_mm(name, mode);
135   fd = sh_open(name, mode, 0666);
136   if (fd < 0)
137     die("Unable to %s file %s: %m",
138         (mode & O_CREAT) ? "create" : "open", name);
139   b = bfdopen_internal(fd, buffer, name);
140   if (mode & O_APPEND)
141     bfd_seek(b, 0, SEEK_END);
142   return b;
143 }
144
145 struct fastbuf *
146 bfdopen(int fd, uns buffer)
147 {
148   byte x[32];
149
150   sprintf(x, "fd%d", fd);
151   return bfdopen_internal(fd, buffer, x);
152 }
153
154 struct fastbuf *
155 bfdopen_shared(int fd, uns buffer)
156 {
157   struct fastbuf *f = bfdopen(fd, buffer);
158   FB_FILE(f)->is_temp_file = -1;
159   return f;
160 }
161
162 #ifdef TEST
163
164 int main(int argc, char **argv)
165 {
166   struct fastbuf *f, *t;
167
168   f = bopen("/etc/profile", O_RDONLY, 16);
169   t = bfdopen(1, 13);
170   bbcopy(f, t, 100);
171   printf("%d %d\n", (int)btell(f), (int)btell(t));
172   bclose(f);
173   bclose(t);
174   return 0;
175 }
176
177 #endif