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