source: trunk/third/nmh/sbr/folder_addmsg.c @ 12455

Revision 12455, 4.5 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12454, which included commits to RCS files with non-trunk default branches.
Line 
1
2/*
3 * folder_addmsg.c -- Link message into folder
4 *
5 * $Id: folder_addmsg.c,v 1.1.1.1 1999-02-07 18:14:08 danw Exp $
6 */
7
8#include <h/mh.h>
9#include <fcntl.h>
10#include <errno.h>
11
12/*
13 * Link message into a folder.  Return the new number
14 * of the message.  If an error occurs, return -1.
15 */
16
17int
18folder_addmsg (struct msgs **mpp, char *msgfile, int selected,
19               int unseen, int preserve)
20{
21    int infd, outfd, linkerr, first_time, msgnum;
22    char *nmsg, newmsg[BUFSIZ];
23    struct msgs *mp;
24    struct stat st1, st2;
25
26    first_time = 1;     /* this is first attempt */
27    mp = *mpp;
28
29    /*
30     * We might need to make several attempts
31     * in order to add the message to the folder.
32     */
33    for (;;) {
34        /*
35         * Get the message number we will attempt to add.
36         */
37        if (first_time) {
38            /* should we preserve the numbering of the message? */
39            if (preserve && (msgnum = m_atoi (msgfile)) > 0) {
40                ;
41            } else if (mp->nummsg == 0) {
42                /* check if we are adding to empty folder */
43                msgnum = 1;
44            } else {
45                /* else use highest message number + 1 */
46                msgnum = mp->hghmsg + 1;
47            }
48            first_time = 0;
49        } else {
50            /* another attempt, so try next higher message number */
51            msgnum++;
52        }
53
54        /*
55         * See if we need more space.  If we need space at the
56         * end, then we allocate space for an addition 100 messages.
57         * If we need space at the beginning of the range, then just
58         * extend message status range to cover this message number.
59         */
60        if (msgnum > mp->hghoff) {
61            if ((mp = folder_realloc (mp, mp->lowoff, msgnum + 100)))
62                *mpp = mp;
63            else {
64                advise (NULL, "unable to allocate folder storage");
65                return -1;
66            }
67        } else if (msgnum < mp->lowoff) {
68            if ((mp = folder_realloc (mp, msgnum, mp->hghoff)))
69                *mpp = mp;
70            else {
71                advise (NULL, "unable to allocate folder storage");
72                return -1;
73            }
74        }
75
76        /*
77         * If a message is already in that slot,
78         * then loop to next available slot.
79         */
80        if (does_exist (mp, msgnum))
81            continue;
82
83        /* setup the bit flags for this message */
84        clear_msg_flags (mp, msgnum);
85        set_exists (mp, msgnum);
86
87        /* should we set the SELECT_UNSEEN bit? */
88        if (unseen) {
89            set_unseen (mp, msgnum);
90        }
91
92        /* should we set the SELECTED bit? */
93        if (selected) {
94            set_selected (mp, msgnum);
95
96            /* check if highest or lowest selected */
97            if (mp->numsel == 0) {
98                mp->lowsel = msgnum;
99                mp->hghsel = msgnum;
100            } else {
101                if (msgnum < mp->lowsel)
102                    mp->lowsel = msgnum;
103                if (msgnum > mp->hghsel)
104                    mp->hghsel = msgnum;
105            }
106
107            /* increment number selected */
108            mp->numsel++;
109        }
110
111        /*
112         * check if this is highest or lowest message
113         */
114        if (mp->nummsg == 0) {
115            mp->lowmsg = msgnum;
116            mp->hghmsg = msgnum;
117        } else {
118            if (msgnum < mp->lowmsg)
119                mp->lowmsg = msgnum;
120            if (msgnum > mp->hghmsg)
121                mp->hghmsg = msgnum;
122        }
123
124        /* increment message count */
125        mp->nummsg++;
126
127        nmsg = m_name (msgnum);
128        snprintf (newmsg, sizeof(newmsg), "%s/%s", mp->foldpath, nmsg);
129
130        /*
131         * Now try to link message into folder
132         */
133        if (link (msgfile, newmsg) != -1) {
134            return msgnum;
135        } else {
136            linkerr = errno;
137
138#ifdef EISREMOTE
139            if (linkerr == EISREMOTE)
140                linkerr = EXDEV;
141#endif /* EISREMOTE */
142
143            /*
144             * Check if the file in our desired location is the same
145             * as the source file.  If so, then just leave it alone
146             * and return.  Otherwise, we will continue the main loop
147             * and try again at another slot (hghmsg+1).
148             */
149            if (linkerr == EEXIST) {
150                if (stat (msgfile, &st2) == 0 && stat (newmsg, &st1) == 0
151                    && st2.st_ino == st1.st_ino) {
152                    return msgnum;
153                } else {
154                    continue;
155                }
156            }
157
158            /*
159             * If link failed because we are trying to link
160             * across devices, then check if there is a message
161             * already in the desired location.  If so, then return
162             * error, else just copy the message.
163             */
164            if (linkerr == EXDEV) {
165                if (stat (newmsg, &st1) == 0) {
166                    advise (NULL, "message %s:%s already exists", newmsg);
167                    return -1;
168                } else {
169                    if ((infd = open (msgfile, O_RDONLY)) == -1) {
170                        advise (msgfile, "unable to open message %s");
171                        return -1;
172                    }
173                    fstat (infd, &st1);
174                    if ((outfd = creat (newmsg, (int) st1.st_mode & 0777)) == -1) {
175                        advise (newmsg, "unable to create");
176                        close (infd);
177                        return -1;
178                    }
179                    cpydata (infd, outfd, msgfile, newmsg);
180                    close (infd);
181                    close (outfd);
182                    return msgnum;
183                }
184            }
185
186            /*
187             * Else, some other type of link error,
188             * so just return error.
189             */
190            advise (newmsg, "error linking %s to", msgfile);
191            return -1;
192        }
193    }
194}
Note: See TracBrowser for help on using the repository browser.