c28b430182f711ceec9103c573ec38fa0b2b00fc
[mmh] / sbr / folder_read.c
1 /*
2 ** folder_read.c -- initialize folder structure and read folder
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/utils.h>
11
12 /* We allocate the `mi' array 1024 elements at a time */
13 #define NUMMSGS  1024
14
15 /*
16 ** 1) Create the folder/message structure
17 ** 2) Read the directory (folder) and temporarily
18 **    record the numbers of the messages we have seen.
19 ** 3) Then allocate the array for message attributes and
20 **    set the initial flags for all messages we've seen.
21 ** 4) Read and initialize the sequence information.
22 */
23
24 struct msgs *
25 folder_read(char *name)
26 {
27         int msgnum, prefix_len, len, *mi;
28         struct msgs *mp;
29         struct stat st;
30         struct dirent *dp;
31         DIR *dd;
32
33         name = getcpy(toabsdir(name));
34         if (!(dd = opendir(name))) {
35                 free(name);
36                 return NULL;
37         }
38
39         if (stat(name, &st) == -1) {
40                 free(name);
41                 return NULL;
42         }
43
44         /* Allocate the main structure for folder information */
45         mp = (struct msgs *) mh_xmalloc((size_t) sizeof(*mp));
46
47         clear_folder_flags(mp);
48         mp->foldpath = name;
49         mp->lowmsg = 0;
50         mp->hghmsg = 0;
51         mp->curmsg = 0;
52         mp->lowsel = 0;
53         mp->hghsel = 0;
54         mp->numsel = 0;
55         mp->nummsg = 0;
56
57         if (access(name, W_OK) == -1)
58                 set_readonly(mp);
59         prefix_len = strlen(backup_prefix);
60
61         /*
62         ** Allocate a temporary place to record the
63         ** name of the messages in this folder.
64         */
65         len = NUMMSGS;
66         mi = (int *) mh_xmalloc((size_t) (len * sizeof(*mi)));
67
68         while ((dp = readdir(dd))) {
69                 if ((msgnum = m_atoi(dp->d_name)) && msgnum > 0) {
70                         /*
71                         ** Check if we need to allocate more
72                         ** temporary elements for message names.
73                         */
74                         if (mp->nummsg >= len) {
75                                 len += NUMMSGS;
76                                 mi = (int *) mh_xrealloc(mi, (size_t) (len * sizeof(*mi)));
77                         }
78
79                         /* Check if this is the first message we've seen */
80                         if (mp->nummsg == 0) {
81                                 mp->lowmsg = msgnum;
82                                 mp->hghmsg = msgnum;
83                         } else {
84                                 /*
85                                 ** Check if this is it the highest or
86                                 ** lowest we've seen?
87                                 */
88                                 if (msgnum < mp->lowmsg)
89                                    mp->lowmsg = msgnum;
90                                 if (msgnum > mp->hghmsg)
91                                    mp->hghmsg = msgnum;
92                         }
93
94                         /*
95                         ** Now increment count, and record message
96                         ** number in a temporary place for now.
97                         */
98                         mi[mp->nummsg++] = msgnum;
99
100                 } else {
101                         switch (dp->d_name[0]) {
102                                 case '.':
103                                 case ',':
104 #ifdef MHE
105                                 case '+':
106 #endif /* MHE */
107                                         continue;
108
109                                 default:
110                                         /*
111                                         ** skip any files beginning with
112                                         ** backup prefix
113                                         */
114                                         if (!strncmp(dp->d_name, backup_prefix, prefix_len))
115                                                 continue;
116
117                                         /* skip the altmsg link file */
118                                         if (!strcmp(dp->d_name, altmsglink))
119                                                 continue;
120
121                                         /*
122                                         ** indicate that there are other
123                                         ** files in folder
124                                         */
125                                         set_other_files(mp);
126                                         continue;
127                         }
128                 }
129         }
130
131         closedir(dd);
132         mp->lowoff = max(mp->lowmsg, 1);
133
134         /* Go ahead and allocate space for 100 additional messages. */
135         mp->hghoff = mp->hghmsg + 100;
136
137         /* for testing, allocate minimal necessary space */
138         /* mp->hghoff = max(mp->hghmsg, 1); */
139
140         /*
141         ** Allocate space for status of each message.
142         */
143         mp->msgstats = mh_xmalloc(MSGSTATSIZE(mp, mp->lowoff, mp->hghoff));
144
145         /*
146         ** Clear all the flag bits for all the message
147         ** status entries we just allocated.
148         */
149         for (msgnum = mp->lowoff; msgnum <= mp->hghoff; msgnum++)
150                 clear_msg_flags(mp, msgnum);
151
152         /*
153         ** Scan through the array of messages we've seen and
154         ** setup the initial flags for those messages in the
155         ** newly allocated mp->msgstats area.
156         */
157         for (msgnum = 0; msgnum < mp->nummsg; msgnum++)
158                 set_exists(mp, mi[msgnum]);
159
160         free(mi);  /* We don't need this anymore */
161
162         /*
163         ** Read and initialize the sequence information.
164         */
165         seq_read(mp);
166
167         return mp;
168 }