Removed the space between function names and the opening parenthesis.
[mmh] / sbr / folder_addmsg.c
1 /*
2 ** folder_addmsg.c -- Link message into 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 <fcntl.h>
11 #include <errno.h>
12
13 /*
14 ** Link message into a folder.  Return the new number
15 ** of the message.  If an error occurs, return -1.
16 */
17
18 int
19 folder_addmsg(struct msgs **mpp, char *msgfile, int selected,
20         int unseen, int preserve, int deleting, char *from_dir)
21 {
22         int infd, outfd, linkerr, msgnum;
23         char *nmsg, newmsg[BUFSIZ];
24         char oldmsg[BUFSIZ];
25         struct msgs *mp;
26         struct stat st1, st2;
27
28         mp = *mpp;
29
30         /* should we preserve the numbering of the message? */
31         if (preserve && (msgnum = m_atoi(msgfile)) > 0) {
32                 ;
33         } else if (mp->nummsg == 0) {
34                 /* check if we are adding to empty folder */
35                 msgnum = 1;
36         } else {
37                 /* else use highest message number + 1 */
38                 msgnum = mp->hghmsg + 1;
39         }
40
41         /*
42         ** We might need to make several attempts
43         ** in order to add the message to the folder.
44         */
45         for (;; msgnum++) {
46
47                 /*
48                 ** See if we need more space.  If we need space at the
49                 ** end, then we allocate space for an addition 100 messages.
50                 ** If we need space at the beginning of the range, then just
51                 ** extend message status range to cover this message number.
52                 */
53                 if (msgnum > mp->hghoff) {
54                         if ((mp = folder_realloc(mp, mp->lowoff, msgnum + 100)))
55                                 *mpp = mp;
56                         else {
57                                 advise(NULL, "unable to allocate folder storage");
58                                 return -1;
59                         }
60                 } else if (msgnum < mp->lowoff) {
61                         if ((mp = folder_realloc(mp, msgnum, mp->hghoff)))
62                                 *mpp = mp;
63                         else {
64                                 advise(NULL, "unable to allocate folder storage");
65                                 return -1;
66                         }
67                 }
68
69                 /*
70                 ** If a message is already in that slot,
71                 ** then loop to next available slot.
72                 */
73                 if (does_exist(mp, msgnum))
74                         continue;
75
76                 /* setup the bit flags for this message */
77                 clear_msg_flags(mp, msgnum);
78                 set_exists(mp, msgnum);
79
80                 /* should we set the SELECT_UNSEEN bit? */
81                 if (unseen) {
82                         set_unseen(mp, msgnum);
83                 }
84
85                 /* should we set the SELECTED bit? */
86                 if (selected) {
87                         set_selected(mp, msgnum);
88
89                         /* check if highest or lowest selected */
90                         if (mp->numsel == 0) {
91                                 mp->lowsel = msgnum;
92                                 mp->hghsel = msgnum;
93                         } else {
94                                 if (msgnum < mp->lowsel)
95                                         mp->lowsel = msgnum;
96                                 if (msgnum > mp->hghsel)
97                                         mp->hghsel = msgnum;
98                         }
99
100                         /* increment number selected */
101                         mp->numsel++;
102                 }
103
104                 /*
105                 ** check if this is highest or lowest message
106                 */
107                 if (mp->nummsg == 0) {
108                         mp->lowmsg = msgnum;
109                         mp->hghmsg = msgnum;
110                 } else {
111                         if (msgnum < mp->lowmsg)
112                                 mp->lowmsg = msgnum;
113                         if (msgnum > mp->hghmsg)
114                                 mp->hghmsg = msgnum;
115                 }
116
117                 /* increment message count */
118                 mp->nummsg++;
119
120                 nmsg = m_name(msgnum);
121                 snprintf(newmsg, sizeof(newmsg), "%s/%s", mp->foldpath, nmsg);
122
123                 /*
124                 ** Now try to link message into folder.  Then run the
125                 ** external hook on the message if one was specified in
126                 ** the context.  Run the refile hook if we're moving the
127                 ** message from one place to another.  We have to construct
128                 ** the from path name for this because it's not there.
129                 ** Run the add hook if the message is getting copied or
130                 ** linked somewhere else.
131                 */
132                 if (link(msgfile, newmsg) != -1) {
133
134                         if (deleting) {
135                                 (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile);
136                                 (void)ext_hook("ref-hook", oldmsg, newmsg);
137                         } else
138                                 (void)ext_hook("add-hook", newmsg, (char *)0);
139
140                         return msgnum;
141                 } else {
142                         linkerr = errno;
143
144 #ifdef EISREMOTE
145                         if (linkerr == EISREMOTE)
146                                 linkerr = EXDEV;
147 #endif /* EISREMOTE */
148
149                         /*
150                         ** Check if the file in our desired location is
151                         ** the same as the source file.  If so, then just
152                         ** leave it alone and return.  Otherwise, we will
153                         ** continue the main loop and try again at another
154                         ** slot (hghmsg+1).
155                         */
156                         if (linkerr == EEXIST) {
157                                 if (stat(msgfile, &st2) == 0 && stat(newmsg, &st1) == 0
158                                         && st2.st_ino == st1.st_ino) {
159                                         return msgnum;
160                                 } else {
161                                         continue;
162                                 }
163                         }
164
165                         /*
166                         ** If link failed because we are trying to link
167                         ** across devices, then check if there is a message
168                         ** already in the desired location.  If so, then return
169                         ** error, else just copy the message.
170                         */
171                         if (linkerr == EXDEV) {
172                                 if (stat(newmsg, &st1) == 0) {
173                                         advise(NULL, "message %s:%s already exists", mp->foldpath, newmsg);
174                                         return -1;
175                                 } else {
176                                         if ((infd = open(msgfile, O_RDONLY)) == -1) {
177                                                 advise(msgfile, "unable to open message %s", msgfile);
178                                                 return -1;
179                                         }
180                                         fstat(infd, &st1);
181                                         if ((outfd = creat(newmsg, (int) st1.st_mode & 0777)) == -1) {
182                                                 advise(newmsg, "unable to create");
183                                                 close(infd);
184                                                 return -1;
185                                         }
186                                         cpydata(infd, outfd, msgfile, newmsg);
187                                         close(infd);
188                                         close(outfd);
189
190                                         if (deleting) {
191                                                 (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile);
192                                                 (void)ext_hook("ref-hook", oldmsg, newmsg);
193                                         } else
194                                                 (void)ext_hook("add-hook", newmsg, (char *)0);
195
196                                         return msgnum;
197                                 }
198                         }
199
200                         /*
201                         ** Else, some other type of link error,
202                         ** so just return error.
203                         */
204                         advise(newmsg, "error linking %s to", msgfile);
205                         return -1;
206                 }
207         }
208 }