X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/1691e80890e5d8ba258c51c214a3e91880e1db2b..d4814561eafc238a9ed2b4fa67ef2755e5e83858:/sbr/folder_addmsg.c?ds=sidebyside diff --git a/sbr/folder_addmsg.c b/sbr/folder_addmsg.c index 6858f4db..a18f1ce7 100644 --- a/sbr/folder_addmsg.c +++ b/sbr/folder_addmsg.c @@ -1,13 +1,19 @@ - -/* - * folder_addmsg.c -- Link message into folder +/* folder_addmsg.c -- Link message into folder * - * $Id$ + * This code is Copyright (c) 2002, by the authors of nmh. See the + * COPYRIGHT file in the root directory of the nmh distribution for + * complete copyright information. */ -#include +#include "h/mh.h" +#include "m_name.h" +#include "cpydata.h" +#include "m_atoi.h" +#include "ext_hook.h" +#include "folder_realloc.h" +#include "folder_addmsg.h" +#include "error.h" #include -#include /* * Link message into a folder. Return the new number @@ -16,40 +22,32 @@ int folder_addmsg (struct msgs **mpp, char *msgfile, int selected, - int unseen, int preserve) + int unseen, int preserve, int deleting, char *from_dir) { - int infd, outfd, linkerr, first_time, msgnum; + int infd, outfd, linkerr, msgnum; char *nmsg, newmsg[BUFSIZ]; + char oldmsg[BUFSIZ]; struct msgs *mp; struct stat st1, st2; - first_time = 1; /* this is first attempt */ mp = *mpp; + /* should we preserve the numbering of the message? */ + if (preserve && (msgnum = m_atoi (msgfile)) > 0) { + ; + } else if (mp->nummsg == 0) { + /* check if we are adding to empty folder */ + msgnum = 1; + } else { + /* else use highest message number + 1 */ + msgnum = mp->hghmsg + 1; + } + /* * We might need to make several attempts * in order to add the message to the folder. */ - for (;;) { - /* - * Get the message number we will attempt to add. - */ - if (first_time) { - /* should we preserve the numbering of the message? */ - if (preserve && (msgnum = m_atoi (msgfile)) > 0) { - ; - } else if (mp->nummsg == 0) { - /* check if we are adding to empty folder */ - msgnum = 1; - } else { - /* else use highest message number + 1 */ - msgnum = mp->hghmsg + 1; - } - first_time = 0; - } else { - /* another attempt, so try next higher message number */ - msgnum++; - } + for (;; msgnum++) { /* * See if we need more space. If we need space at the @@ -58,19 +56,17 @@ folder_addmsg (struct msgs **mpp, char *msgfile, int selected, * extend message status range to cover this message number. */ if (msgnum > mp->hghoff) { - if ((mp = folder_realloc (mp, mp->lowoff, msgnum + 100))) - *mpp = mp; - else { - advise (NULL, "unable to allocate folder storage"); + if (!(mp = folder_realloc (mp, mp->lowoff, msgnum + 100))) { + inform("unable to allocate folder storage"); return -1; - } + } + *mpp = mp; } else if (msgnum < mp->lowoff) { - if ((mp = folder_realloc (mp, msgnum, mp->hghoff))) - *mpp = mp; - else { - advise (NULL, "unable to allocate folder storage"); + if (!(mp = folder_realloc (mp, msgnum, mp->hghoff))) { + inform("unable to allocate folder storage"); return -1; - } + } + *mpp = mp; } /* @@ -128,67 +124,85 @@ folder_addmsg (struct msgs **mpp, char *msgfile, int selected, snprintf (newmsg, sizeof(newmsg), "%s/%s", mp->foldpath, nmsg); /* - * Now try to link message into folder + * Now try to link message into folder. + * Then run the external hook on the message if one was specified in the context. + * Run the refile hook if we're moving the message from one place to another. + * We have to construct the from path name for this because it's not there. + * Run the add hook if the message is getting copied or linked somewhere else. */ if (link (msgfile, newmsg) != -1) { + if (deleting) { + (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile); + (void)ext_hook("ref-hook", oldmsg, newmsg); + } + else + (void)ext_hook("add-hook", newmsg, NULL); + return msgnum; - } else { - linkerr = errno; + } + linkerr = errno; #ifdef EISREMOTE - if (linkerr == EISREMOTE) - linkerr = EXDEV; + if (linkerr == EISREMOTE) + linkerr = EXDEV; #endif /* EISREMOTE */ - /* - * Check if the file in our desired location is the same - * as the source file. If so, then just leave it alone - * and return. Otherwise, we will continue the main loop - * and try again at another slot (hghmsg+1). - */ - if (linkerr == EEXIST) { - if (stat (msgfile, &st2) == 0 && stat (newmsg, &st1) == 0 - && st2.st_ino == st1.st_ino) { - return msgnum; - } else { - continue; - } - } - - /* - * If link failed because we are trying to link - * across devices, then check if there is a message - * already in the desired location. If so, then return - * error, else just copy the message. - */ - if (linkerr == EXDEV) { - if (stat (newmsg, &st1) == 0) { - advise (NULL, "message %s:%s already exists", newmsg); - return -1; - } else { - if ((infd = open (msgfile, O_RDONLY)) == -1) { - advise (msgfile, "unable to open message %s"); - return -1; - } - fstat (infd, &st1); - if ((outfd = creat (newmsg, (int) st1.st_mode & 0777)) == -1) { - advise (newmsg, "unable to create"); - close (infd); - return -1; - } - cpydata (infd, outfd, msgfile, newmsg); - close (infd); - close (outfd); - return msgnum; - } - } - - /* - * Else, some other type of link error, - * so just return error. - */ - advise (newmsg, "error linking %s to", msgfile); - return -1; - } + /* + * Check if the file in our desired location is the same + * as the source file. If so, then just leave it alone + * and return. Otherwise, we will continue the main loop + * and try again at another slot (hghmsg+1). + */ + if (linkerr == EEXIST) { + if (stat (msgfile, &st2) == 0 && stat (newmsg, &st1) == 0 + && st2.st_ino == st1.st_ino) { + return msgnum; + } + continue; + } + + /* + * If link failed because we are trying to link + * across devices, then check if there is a message + * already in the desired location. If so, then return + * error, else just copy the message. + * Cygwin with FAT32 filesystem produces EPERM. + */ + if (linkerr == EXDEV || linkerr == EPERM) { + if (stat (newmsg, &st1) == 0) { + inform("message %s:%s already exists", mp->foldpath, newmsg); + return -1; + } + + if ((infd = open (msgfile, O_RDONLY)) == -1) { + advise (msgfile, "unable to open message %s", msgfile); + return -1; + } + fstat (infd, &st1); + if ((outfd = creat (newmsg, (int) st1.st_mode & 0777)) == -1) { + advise (newmsg, "unable to create"); + close (infd); + return -1; + } + cpydata (infd, outfd, msgfile, newmsg); + close (infd); + close (outfd); + + if (deleting) { + (void)snprintf(oldmsg, sizeof (oldmsg), "%s/%s", from_dir, msgfile); + (void)ext_hook("ref-hook", oldmsg, newmsg); + } + else + (void)ext_hook("add-hook", newmsg, NULL); + + return msgnum; + } + + /* + * Else, some other type of link error, + * so just return error. + */ + advise (newmsg, "error linking %s to", msgfile); + return -1; } }