]> git.neil.brown.name Git - wiggle.git/blob - load.c
Allow load_file to load segments too.
[wiggle.git] / load.c
1 /*
2  * wiggle - apply rejected patches
3  *
4  * Copyright (C) 2003 Neil Brown <neilb@cse.unsw.edu.au>
5  *
6  *
7  *    This program is free software; you can redistribute it and/or modify
8  *    it under the terms of the GNU General Public License as published by
9  *    the Free Software Foundation; either version 2 of the License, or
10  *    (at your option) any later version.
11  *
12  *    This program is distributed in the hope that it will be useful,
13  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *    GNU General Public License for more details.
16  *
17  *    You should have received a copy of the GNU General Public License
18  *    along with this program; if not, write to the Free Software Foundation, Inc.,
19  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  *    Author: Neil Brown
22  *    Email: <neilb@suse.de>
23  */
24
25 /*
26  * read in files
27  *
28  * Files are read in whole and stored in a
29  * struct stream {char*, len}
30  *
31  *
32  * loading the file "-" reads from stdin which might require
33  * reading into several buffers
34  */
35
36 #include        "wiggle.h"
37 #include        <sys/types.h>
38 #include        <sys/stat.h>
39 #include        <unistd.h>
40 #include        <fcntl.h>
41 #include        <stdlib.h>
42
43 static void join_streams(struct stream list[], int cnt)
44 {
45         /* join all the streams in the list (upto body=NULL)
46          * into one by re-allocing list[0].body and copying
47          */
48         int len = 0;
49         int i;
50         char *c;
51
52         for (i = 0; i < cnt ; i++)
53                 len += list[i].len;
54
55         c = realloc(list[0].body, len+1);
56         if (c == NULL)
57                 die();
58
59         list[0].body = c;
60         c  += list[0].len;
61         list[0].len = len;
62         for (i = 1; i < cnt; i++) {
63                 memcpy(c, list[i].body, list[i].len);
64                 c += list[i].len;
65                 list[i].len = 0;
66                 free(list[i].body);
67         }
68         c[0] = 0;
69 }
70
71 static struct stream load_regular(int fd)
72 {
73         struct stat stb;
74         struct stream s;
75         fstat(fd, &stb);
76
77         s.len = stb.st_size;
78         s.body = xmalloc(s.len+1);
79         if (read(fd, s.body, s.len) != s.len)
80                 die();
81
82         s.body[s.len] = 0;
83         return s;
84 }
85
86 static struct stream load_other(int fd)
87 {
88
89         struct stream list[10];
90         int i = 0;
91
92         while (1) {
93                 list[i].body = xmalloc(8192);
94                 list[i].len = read(fd, list[i].body, 8192);
95                 if (list[i].len < 0)
96                         die();
97                 if (list[i].len == 0)
98                         break;
99                 i++;
100                 if (i == 10) {
101                         join_streams(list, i);
102                         i = 1;
103                 }
104         }
105         join_streams(list, i);
106         return list[0];
107 }
108
109 struct stream load_segment(FILE *f,
110                            unsigned int start, unsigned int end)
111 {
112         struct stream s;
113         s.len = end - start;
114         s.body = xmalloc(s.len);
115         fseek(f, start, 0);
116         if (fread(s.body, 1, s.len, f) != (size_t)s.len)
117                 die();
118         return s;
119 }
120
121 struct stream load_file(char *name)
122 {
123         struct stream s;
124         struct stat stb;
125         int fd;
126         int start, end;
127         int prefix_len = 0;
128
129         s.body = NULL;
130         s.len = 0;
131         if (sscanf(name, "_wiggle_:%d:%d:%n", &start, &end,
132                    &prefix_len) >= 2 && prefix_len > 0) {
133                 FILE *f = fopen(name + prefix_len, "r");
134                 if (f) {
135                         s = load_segment(f, start, end);
136                         fclose(f);
137                 } else {
138                         s.body = NULL;
139                         s.len = 0;
140                 }
141         } else {
142                 if (strcmp(name, "-") == 0)
143                         fd = 0;
144                 else {
145                         fd = open(name, O_RDONLY);
146                         if (fd < 0)
147                                 return s;
148                 }
149
150                 if (fstat(fd, &stb) == 0) {
151
152                         if (S_ISREG(stb.st_mode))
153                                 s = load_regular(fd);
154                         else
155                                 s = load_other(fd);
156                 }
157                 close(fd);
158         }
159         return s;
160 }
161