uidl: start from the last matched uidl in uidl_find()
[pop3.git] / uidl.c
blob2abd9870a8309212df6392b08c366e257cd1a27d
1 #include <fcntl.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include "uidl.h"
10 struct uidl {
11 char *txt;
12 int fd;
13 char *prev; /* the previous matched position */
16 static int file_size(int fd)
18 struct stat st;
19 fstat(fd, &st);
20 return st.st_size;
23 static int xread(int fd, char *buf, int len)
25 int nr = 0;
26 while (nr < len) {
27 int cr = read(fd, buf + nr, len - nr);
28 if (cr == -1)
29 break;
30 nr += cr;
32 return nr;
35 struct uidl *uidl_read(char *filename)
37 struct uidl *uidl = malloc(sizeof(*uidl));
38 int len;
39 memset(uidl, 0, sizeof(*uidl));
40 uidl->fd = open(filename, O_RDWR | O_CREAT, 0600);
41 len = file_size(uidl->fd);
42 lseek(uidl->fd, 0, SEEK_SET);
43 uidl->txt = malloc(len + 1);
44 xread(uidl->fd, uidl->txt, len);
45 uidl->txt[len] = '\0';
46 lseek(uidl->fd, 0, SEEK_END);
47 return uidl;
50 static char *find_str(char *s, char *id)
52 int len = strlen(id);
53 while (s && *s) {
54 if (!strncmp(s, id, len) && s[len] == '\n')
55 return s;
56 s = strchr(s, '\n');
57 s = s ? s + 1 : s;
59 return NULL;
62 int uidl_find(struct uidl *uidl, char *id)
64 if (uidl->prev)
65 uidl->prev = find_str(uidl->prev, id);
66 if (!uidl->prev)
67 uidl->prev = find_str(uidl->txt, id);
68 return uidl->prev != NULL;
71 void uidl_add(struct uidl *uidl, char *id)
73 char kw[256];
74 snprintf(kw, sizeof(kw), "%s\n", id);
75 write(uidl->fd, kw, strlen(kw));
78 void uidl_save(struct uidl *uidl)
80 close(uidl->fd);
81 free(uidl->txt);
82 free(uidl);