]> rtime.felk.cvut.cz Git - notmuch.git/blob - contrib/notmuch-deliver/maildrop/maildir/maildiropen.c
254287370f74deccbb74c96986721c6da355ee34
[notmuch.git] / contrib / notmuch-deliver / maildrop / maildir / 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
26 char *maildir_getlink(const char *filename)
27 {
28 #if     HAVE_READLINK
29 size_t  bufsiz;
30 char    *buf;
31
32         bufsiz=0;
33         buf=0;
34
35         for (;;)
36         {
37         int     n;
38
39                 if (buf)        free(buf);
40                 bufsiz += 256;
41                 if ((buf=malloc(bufsiz)) == 0)
42                 {
43                         perror("malloc");
44                         return (0);
45                 }
46                 if ((n=readlink(filename, buf, bufsiz)) < 0)
47                 {
48                         free(buf);
49                         return (0);
50                 }
51                 if (n < bufsiz)
52                 {
53                         buf[n]=0;
54                         break;
55                 }
56         }
57         return (buf);
58 #else
59         return (0);
60 #endif
61 }
62
63 int maildir_semisafeopen(const char *path, int mode, int perm)
64 {
65
66 #if     HAVE_READLINK
67
68 char    *l=maildir_getlink(path);
69
70         if (l)
71         {
72         int     f;
73
74                 if (*l != '/')
75                 {
76                 char    *q=malloc(strlen(path)+strlen(l)+2);
77                 char    *s;
78
79                         if (!q)
80                         {
81                                 free(l);
82                                 return (-1);
83                         }
84
85                         strcpy(q, path);
86                         if ((s=strchr(q, '/')) != 0)
87                                 s[1]=0;
88                         else    *q=0;
89                         strcat(q, l);
90                         free(l);
91                         l=q;
92                 }
93
94                 f=maildir_safeopen(l, mode, perm);
95
96                 free(l);
97                 return (f);
98         }
99 #endif
100
101         return (maildir_safeopen(path, mode, perm));
102 }
103                 
104 int maildir_safeopen(const char *path, int mode, int perm)
105 {
106         struct  stat    stat1;
107
108         return maildir_safeopen_stat(path, mode, perm, &stat1);
109 }
110
111 int maildir_safeopen_stat(const char *path, int mode, int perm,
112                           struct stat *stat1)
113 {
114         struct  stat    stat2;
115
116         int     fd=open(path, mode
117 #ifdef  O_NONBLOCK
118                         | O_NONBLOCK
119 #else
120                         | O_NDELAY
121 #endif
122                         , perm);
123
124         if (fd < 0)     return (fd);
125         if (fcntl(fd, F_SETFL, (mode & O_APPEND)) || fstat(fd, stat1)
126             || lstat(path, &stat2))
127         {
128                 close(fd);
129                 return (-1);
130         }
131
132         if (stat1->st_dev != stat2.st_dev || stat1->st_ino != stat2.st_ino)
133         {
134                 close(fd);
135                 errno=ENOENT;
136                 return (-1);
137         }
138
139         return (fd);
140 }