2 ** folder_addmsg.c -- Link message into folder
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.
14 ** Link message into a folder. Return the new number
15 ** of the message. If an error occurs, return -1.
19 folder_addmsg(struct msgs **mpp, char *msgfile, int selected,
20 int unseen, int preserve, int deleting, char *from_dir)
22 int infd, outfd, linkerr, msgnum;
23 char *nmsg, newmsg[BUFSIZ];
30 /* should we preserve the numbering of the message? */
31 if (preserve && (msgnum = m_atoi(msgfile)) > 0) {
33 } else if (mp->nummsg == 0) {
34 /* check if we are adding to empty folder */
37 /* else use highest message number + 1 */
38 msgnum = mp->hghmsg + 1;
42 ** We might need to make several attempts
43 ** in order to add the message to the folder.
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.
53 if (msgnum > mp->hghoff) {
54 if ((mp = folder_realloc(mp, mp->lowoff, msgnum + 100)))
57 advise(NULL, "unable to allocate folder storage");
60 } else if (msgnum < mp->lowoff) {
61 if ((mp = folder_realloc(mp, msgnum, mp->hghoff)))
64 advise(NULL, "unable to allocate folder storage");
70 ** If a message is already in that slot,
71 ** then loop to next available slot.
73 if (does_exist(mp, msgnum))
76 /* setup the bit flags for this message */
77 clear_msg_flags(mp, msgnum);
78 set_exists(mp, msgnum);
80 /* should we set the SELECT_UNSEEN bit? */
82 set_unseen(mp, msgnum);
85 /* should we set the SELECTED bit? */
87 set_selected(mp, msgnum);
89 /* check if highest or lowest selected */
90 if (mp->numsel == 0) {
94 if (msgnum < mp->lowsel)
96 if (msgnum > mp->hghsel)
100 /* increment number selected */
105 ** check if this is highest or lowest message
107 if (mp->nummsg == 0) {
111 if (msgnum < mp->lowmsg)
113 if (msgnum > mp->hghmsg)
117 /* increment message count */
120 nmsg = m_name(msgnum);
121 snprintf(newmsg, sizeof(newmsg), "%s/%s", mp->foldpath, nmsg);
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.
132 if (link(msgfile, newmsg) != -1) {
135 (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile);
136 (void)ext_hook("ref-hook", oldmsg, newmsg);
138 (void)ext_hook("add-hook", newmsg, (char *)0);
145 if (linkerr == EISREMOTE)
147 #endif /* EISREMOTE */
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
156 if (linkerr == EEXIST) {
157 if (stat(msgfile, &st2) == 0 && stat(newmsg, &st1) == 0
158 && st2.st_ino == st1.st_ino) {
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.
171 if (linkerr == EXDEV) {
172 if (stat(newmsg, &st1) == 0) {
173 advise(NULL, "message %s:%s already exists", mp->foldpath, newmsg);
176 if ((infd = open(msgfile, O_RDONLY)) == -1) {
177 advise(msgfile, "unable to open message %s", msgfile);
181 if ((outfd = creat(newmsg, (int) st1.st_mode & 0777)) == -1) {
182 advise(newmsg, "unable to create");
186 cpydata(infd, outfd, msgfile, newmsg);
191 (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile);
192 (void)ext_hook("ref-hook", oldmsg, newmsg);
194 (void)ext_hook("add-hook", newmsg, (char *)0);
201 ** Else, some other type of link error,
202 ** so just return error.
204 advise(newmsg, "error linking %s to", msgfile);