3 * folder_addmsg.c -- Link message into folder
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
15 * Link message into a folder. Return the new number
16 * of the message. If an error occurs, return -1.
20 folder_addmsg (struct msgs **mpp, char *msgfile, int selected,
21 int unseen, int preserve, int deleting, char *from_dir)
23 int infd, outfd, linkerr, first_time, msgnum;
24 char *nmsg, newmsg[BUFSIZ];
29 first_time = 1; /* this is first attempt */
33 * We might need to make several attempts
34 * in order to add the message to the folder.
38 * Get the message number we will attempt to add.
41 /* should we preserve the numbering of the message? */
42 if (preserve && (msgnum = m_atoi (msgfile)) > 0) {
44 } else if (mp->nummsg == 0) {
45 /* check if we are adding to empty folder */
48 /* else use highest message number + 1 */
49 msgnum = mp->hghmsg + 1;
53 /* another attempt, so try next higher message number */
58 * See if we need more space. If we need space at the
59 * end, then we allocate space for an addition 100 messages.
60 * If we need space at the beginning of the range, then just
61 * extend message status range to cover this message number.
63 if (msgnum > mp->hghoff) {
64 if ((mp = folder_realloc (mp, mp->lowoff, msgnum + 100)))
67 advise (NULL, "unable to allocate folder storage");
70 } else if (msgnum < mp->lowoff) {
71 if ((mp = folder_realloc (mp, msgnum, mp->hghoff)))
74 advise (NULL, "unable to allocate folder storage");
80 * If a message is already in that slot,
81 * then loop to next available slot.
83 if (does_exist (mp, msgnum))
86 /* setup the bit flags for this message */
87 clear_msg_flags (mp, msgnum);
88 set_exists (mp, msgnum);
90 /* should we set the SELECT_UNSEEN bit? */
92 set_unseen (mp, msgnum);
95 /* should we set the SELECTED bit? */
97 set_selected (mp, msgnum);
99 /* check if highest or lowest selected */
100 if (mp->numsel == 0) {
104 if (msgnum < mp->lowsel)
106 if (msgnum > mp->hghsel)
110 /* increment number selected */
115 * check if this is highest or lowest message
117 if (mp->nummsg == 0) {
121 if (msgnum < mp->lowmsg)
123 if (msgnum > mp->hghmsg)
127 /* increment message count */
130 nmsg = m_name (msgnum);
131 snprintf (newmsg, sizeof(newmsg), "%s/%s", mp->foldpath, nmsg);
134 * Now try to link message into folder.
135 * Then run the external hook on the message if one was specified in the context.
136 * Run the refile hook if we're moving the message from one place to another.
137 * We have to construct the from path name for this because it's not there.
138 * Run the add hook if the message is getting copied or linked somewhere else.
140 if (link (msgfile, newmsg) != -1) {
143 (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile);
144 (void)ext_hook("ref-hook", oldmsg, newmsg);
147 (void)ext_hook("add-hook", newmsg, (char *)0);
154 if (linkerr == EISREMOTE)
156 #endif /* EISREMOTE */
159 * Check if the file in our desired location is the same
160 * as the source file. If so, then just leave it alone
161 * and return. Otherwise, we will continue the main loop
162 * and try again at another slot (hghmsg+1).
164 if (linkerr == EEXIST) {
165 if (stat (msgfile, &st2) == 0 && stat (newmsg, &st1) == 0
166 && st2.st_ino == st1.st_ino) {
174 * If link failed because we are trying to link
175 * across devices, then check if there is a message
176 * already in the desired location. If so, then return
177 * error, else just copy the message.
179 if (linkerr == EXDEV) {
180 if (stat (newmsg, &st1) == 0) {
181 advise (NULL, "message %s:%s already exists", mp->foldpath, newmsg);
184 if ((infd = open (msgfile, O_RDONLY)) == -1) {
185 advise (msgfile, "unable to open message %s", msgfile);
189 if ((outfd = creat (newmsg, (int) st1.st_mode & 0777)) == -1) {
190 advise (newmsg, "unable to create");
194 cpydata (infd, outfd, msgfile, newmsg);
199 (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile);
200 (void)ext_hook("ref-hook", oldmsg, newmsg);
203 (void)ext_hook("add-hook", newmsg, (char *)0);
210 * Else, some other type of link error,
211 * so just return error.
213 advise (newmsg, "error linking %s to", msgfile);