libdebian-installer
Functions
RFC822 parser

Functions

int di_parser_rfc822_read (char *begin, size_t size, di_parser_info *fieldinfo, di_parser_read_entry_new entry_new, di_parser_read_entry_finish entry_finish, void *user_data)
 
int di_parser_rfc822_read_file (const char *file, di_parser_info *fieldinfo, di_parser_read_entry_new entry_new, di_parser_read_entry_finish entry_finish, void *user_data)
 
int di_parser_rfc822_write_file (const char *file, di_parser_info *fieldinfo, di_parser_write_entry_next entry_next, void *user_data)
 

Detailed Description

Function Documentation

int di_parser_rfc822_read ( char *  begin,
size_t  size,
di_parser_info fieldinfo,
di_parser_read_entry_new  entry_new,
di_parser_read_entry_finish  entry_finish,
void *  user_data 
)

Parse a rfc822 formated file

Parameters
beginbegin of memory segment
sizesize of memory segment
fieldinfoparser info
entry_newfunction which is called before each entry, may return the new entry or return NULL
entry_finishfunction which is called after each entry, return non-0 aborts the parsing
user_datauser_data for parser functions
Returns
number of parsed entries

References di_hash_table_lookup(), di_warning, di_parser_info::modifier, di_parser_fieldinfo::read, di_rstring::size, di_rstring::string, di_parser_info::table, and di_parser_info::wildcard.

Referenced by di_parser_rfc822_read_file().

42 {
43  char *cur, *end;
44  char *field_begin, *field_end;
45 #if MODIFIER
46  char *field_modifier_begin, *field_modifier_end;
47 #endif
48  char *value_begin, *value_end;
49 #ifndef HAVE_MEMRCHR
50  char *temp;
51 #endif
52  int nr = 0;
53  size_t readsize;
54  size_t field_size;
55 #if MODIFIER
56  size_t field_modifier_size;
57 #endif
58  size_t value_size;
59  const di_parser_fieldinfo *fip = NULL;
60  di_rstring field_string;
61  di_rstring field_modifier_string;
62  di_rstring value_string;
63  void *act = NULL;
64  bool pgp_mode = false;
65  const char pgp_begin_msg[] = "-----BEGIN PGP SIGNED MESSAGE-----";
66  const char pgp_begin_sig[] = "-----BEGIN PGP SIGNATURE-----";
67 
68  cur = begin;
69  end = begin + size;
70 
71  if (!strncmp(cur, pgp_begin_msg, strlen(pgp_begin_msg)))
72  {
73  pgp_mode = true;
74  // Skip PGP header
75  cur = strstr (cur, "\n\n");
76  }
77 
78  while (cur < end)
79  {
80  if (*cur == '\n')
81  {
82  cur++;
83  continue;
84  }
85 
86  nr++;
87 
88  if (entry_new)
89  act = entry_new (user_data);
90  else
91  act = NULL;
92 
93  while (1)
94  {
95  if (pgp_mode && !strncmp(cur, pgp_begin_sig, strlen(pgp_begin_sig)))
96  {
97  // Let's exit, the rest of the file is not interesting
98  cur += size;
99  break;
100  }
101 
102  field_begin = cur;
103  readsize = end - field_begin < READSIZE ? end - field_begin : READSIZE;
104  if (!readsize)
105  break;
106  field_end = memchr (cur, ':', readsize);
107 #if MODIFIER
108  field_modifier_end = field_end;
109 #endif
110  if (!field_end)
111  {
112  di_warning ("parser_rfc822: Iek! Don't find end of field!");
113  return -1;
114  }
115  field_size = field_end - field_begin;
116 
117 #if MODIFIER
118 #ifdef HAVE_MEMRCHR
119  if ((field_modifier_begin = memrchr (field_begin, '-', field_end - field_begin)))
120  field_modifier_begin++;
121  if (field_modifier_begin)
122 #else
123  field_modifier_begin = field_begin;
124  while ((temp = memchr (field_modifier_begin, '-', field_end - field_modifier_begin)))
125  field_modifier_begin = temp + 1;
126  if (field_modifier_begin != field_begin)
127 #endif
128  {
129  field_modifier_size = field_modifier_end - field_modifier_begin;
130  }
131  else
132  {
133  field_modifier_begin = 0;
134  field_modifier_size = 0;
135  }
136 #endif
137 
138  value_begin = field_end + 1;
139  while (value_begin < end && (*value_begin == ' ' || *value_begin == '\t'))
140  value_begin++;
141  readsize = end - field_begin < READSIZE ? end - field_begin : READSIZE;
142  value_end = memchr (field_begin, '\n', readsize);
143  if (!value_end)
144  {
145  di_warning ("parser_rfc822: Iek! Don't find end of value!");
146  return -1;
147  }
148  if (value_end < field_end)
149  {
150  di_warning ("parser_rfc822: Iek! Don't find end of field, it seems to be after the end of the line!");
151  return -1;
152  }
153 
154  /* while (isblank (value_end[1])) FIXME: C99 */
155  while (value_end[1] == ' ' || value_end[1] == '\t')
156  {
157  readsize = end - value_end + 1 < READSIZE ? end - value_end + 1 : READSIZE;
158  if ((value_end = memchr (value_end + 1, '\n', readsize)) == NULL)
159  {
160  di_warning ("Iek! Don't find end of large value\n");
161  return -1;
162  }
163  }
164  value_size = value_end - value_begin;
165 
166  field_string.string = field_begin;
167  field_string.size = field_size;
168  value_string.string = value_begin;
169  value_string.size = value_size;
170 
171  fip = di_hash_table_lookup (info->table, &field_string);
172 
173  if (fip)
174  {
175  fip->read (&act, fip, NULL, &value_string, user_data);
176  goto next;
177  }
178 
179 #if MODIFIER
180  if (info->wildcard)
181  goto wildcard;
182  else if (!info->modifier)
183  goto next;
184 
185  field_string.size = field_size - field_modifier_size - 1;
186 
187  fip = di_hash_table_lookup (info->table, &field_string);
188 
189  if (fip)
190  {
191  field_modifier_string.string = field_modifier_begin;
192  field_modifier_string.size = field_modifier_size;
193 
194  fip->read (&act, fip, &field_modifier_string, &value_string, user_data);
195 
196  goto next;
197  }
198 #endif
199 
200  if (!info->wildcard)
201  goto next;
202 
203 #if MODIFIER
204 wildcard:
205 #endif
206  field_string.size = 0;
207 
208  fip = di_hash_table_lookup (info->table, &field_string);
209 
210  if (fip)
211  {
212  field_modifier_string.string = field_begin;
213  field_modifier_string.size = field_size;
214 
215  fip->read (&act, fip, &field_modifier_string, &value_string, user_data);
216  }
217 
218 next:
219  cur = value_end + 1;
220  if (cur >= end || *cur == '\n')
221  break;
222  }
223 
224  if (entry_finish && entry_finish (act, user_data))
225  return -1;
226  }
227 
228  return nr;
229 }
int di_parser_rfc822_read_file ( const char *  file,
di_parser_info fieldinfo,
di_parser_read_entry_new  entry_new,
di_parser_read_entry_finish  entry_finish,
void *  user_data 
)

Parse a rfc822 formated file

Parameters
filefilename
fieldinfoparser info
entry_newfunction which is called before each entry, may return the new entry or return NULL
entry_finishfunction which is called after each entry, return non-0 aborts the parsing
user_datauser_data for parser functions
Returns
number of parsed entries

References di_parser_rfc822_read().

Referenced by di_release_read_file().

232 {
233  struct stat statbuf;
234  char *begin;
235  int fd, ret = -1;
236 
237  if ((fd = open (file, O_RDONLY)) < 0)
238  return ret;
239  if (fstat (fd, &statbuf))
240  goto cleanup;
241  if (!statbuf.st_size)
242  {
243  ret = 0;
244  goto cleanup;
245  }
246  begin = mmap (NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
247  if (begin == MAP_FAILED)
248  goto cleanup;
249  madvise (begin, statbuf.st_size, MADV_SEQUENTIAL);
250 
251  ret = di_parser_rfc822_read (begin, statbuf.st_size, info, entry_new, entry_finish, user_data);
252 
253  munmap (begin, statbuf.st_size);
254 
255 cleanup:
256  close (fd);
257 
258  return ret;
259 }
int di_parser_rfc822_write_file ( const char *  file,
di_parser_info fieldinfo,
di_parser_write_entry_next  entry_next,
void *  user_data 
)

Dump a rfc822 formated file

Parameters
filefilename
fieldinfoparser info
entry_nextfunction which is called to gather the next entry
user_datauser_data for parser functions
Returns
number of dumped entries

References di_slist_node::data, di_slist::head, di_parser_info::list, di_slist_node::next, and di_parser_fieldinfo::write.

271 {
272  int nr = 0;
273  const di_parser_fieldinfo *fip;
274  void *act = NULL, *state_data = NULL;
275  di_slist_node *node;
276  FILE *f;
277  char tmpfile[PATH_MAX];
278 
279 
280  if (!strncmp (file, "-", 1))
281  {
282  tmpfile[0] = '\0';
283  f = stdout;
284  }
285  else
286  {
287  snprintf (tmpfile, sizeof (tmpfile), "%s.tmp", file);
288  f = fopen (tmpfile, "w");
289  }
290 
291  if (!f)
292  return -1;
293 
294  while (1)
295  {
296  act = entry_next (&state_data, user_data);
297  if (!act)
298  break;
299 
300  nr++;
301 
302  for (node = info->list.head; node; node = node->next)
303  {
304  fip = node->data;
305  if (fip->write)
306  fip->write (&act, fip, callback, f, user_data);
307  }
308  fputc ('\n', f);
309  }
310 
311  if (*tmpfile)
312  {
313  fclose (f);
314  if (rename (tmpfile, file))
315  return -1;
316  }
317 
318  return nr;
319 }