]> git.notmuchmail.org Git - notmuch/blob - contrib/notmuch-deliver/src/maildiropen.c
5071df7681ea6c052700337e3ad2ded7acb3ddc2
[notmuch] / contrib / notmuch-deliver / src / maildiropen.c
1 /*
2 ** Copyright 2000 Double Precision, Inc.
3 ** See COPYING for distribution information.
4 */
5
6 #if HAVE_CONFIG_H
7 #include "config.h"
8 #endif
9
10 #include        <sys/types.h>
11 #include        <sys/stat.h>
12 #include        <string.h>
13 #include        <stdlib.h>
14 #include        <time.h>
15 #if     HAVE_UNISTD_H
16 #include        <unistd.h>
17 #endif
18 #include        <stdio.h>
19 #include        <ctype.h>
20 #include        <errno.h>
21 #include        <fcntl.h>
22
23 #include        "maildirmisc.h"
24
25 static const char rcsid[]="$Id: maildiropen.c,v 1.8 2003/01/19 16:39:52 mrsam Exp $";
26
27 char *maildir_getlink(const char *filename)
28 {
29 #if     HAVE_READLINK
30 size_t  bufsiz;
31 char    *buf;
32
33         bufsiz=0;
34         buf=0;
35
36         for (;;)
37         {
38         int     n;
39
40                 if (buf)        free(buf);
41                 bufsiz += 256;
42                 if ((buf=malloc(bufsiz)) == 0)
43                 {
44                         perror("malloc");
45                         return (0);
46                 }
47                 if ((n=readlink(filename, buf, bufsiz)) < 0)
48                 {
49                         free(buf);
50                         return (0);
51                 }
52                 if (n < bufsiz)
53                 {
54                         buf[n]=0;
55                         break;
56                 }
57         }
58         return (buf);
59 #else
60         return (0);
61 #endif
62 }
63
64 int maildir_semisafeopen(const char *path, int mode, int perm)
65 {
66
67 #if     HAVE_READLINK
68
69 char    *l=maildir_getlink(path);
70
71         if (l)
72         {
73         int     f;
74
75                 if (*l != '/')
76                 {
77                 char    *q=malloc(strlen(path)+strlen(l)+2);
78                 char    *s;
79
80                         if (!q)
81                         {
82                                 free(l);
83                                 return (-1);
84                         }
85
86                         strcpy(q, path);
87                         if ((s=strchr(q, '/')) != 0)
88                                 s[1]=0;
89                         else    *q=0;
90                         strcat(q, l);
91                         free(l);
92                         l=q;
93                 }
94
95                 f=maildir_safeopen(l, mode, perm);
96
97                 free(l);
98                 return (f);
99         }
100 #endif
101
102         return (maildir_safeopen(path, mode, perm));
103 }
104                 
105 int maildir_safeopen(const char *path, int mode, int perm)
106 {
107         struct  stat    stat1;
108
109         return maildir_safeopen_stat(path, mode, perm, &stat1);
110 }
111
112 int maildir_safeopen_stat(const char *path, int mode, int perm,
113                           struct stat *stat1)
114 {
115         struct  stat    stat2;
116
117         int     fd=open(path, mode
118 #ifdef  O_NONBLOCK
119                         | O_NONBLOCK
120 #else
121                         | O_NDELAY
122 #endif
123                         , perm);
124
125         if (fd < 0)     return (fd);
126         if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, stat1)
127             || lstat(path, &stat2))
128         {
129                 close(fd);
130                 return (-1);
131         }
132
133         if (stat1->st_dev != stat2.st_dev || stat1->st_ino != stat2.st_ino)
134         {
135                 close(fd);
136                 errno=ENOENT;
137                 return (-1);
138         }
139
140         return (fd);
141 }