"snoozing" with notmuch?
[notmuch-archives.git] / 84 / 585bad83fdf29e047afd4615714cf6a8ab556a
1 Return-Path: <jani@nikula.org>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 635A1431FAF\r
6         for <notmuch@notmuchmail.org>; Tue,  8 May 2012 01:33:23 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id cVoVnBSJkCCE for <notmuch@notmuchmail.org>;\r
16         Tue,  8 May 2012 01:33:22 -0700 (PDT)\r
17 Received: from mail-qc0-f181.google.com (mail-qc0-f181.google.com\r
18         [209.85.216.181]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
19         (No client certificate requested)\r
20         by olra.theworths.org (Postfix) with ESMTPS id 5AFAA431FAE\r
21         for <notmuch@notmuchmail.org>; Tue,  8 May 2012 01:33:22 -0700 (PDT)\r
22 Received: by qcsk26 with SMTP id k26so167726qcs.26\r
23         for <notmuch@notmuchmail.org>; Tue, 08 May 2012 01:33:21 -0700 (PDT)\r
24 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;\r
25         d=google.com; s=20120113;\r
26         h=from:to:cc:subject:in-reply-to:references:user-agent:date\r
27         :message-id:mime-version:content-type:x-gm-message-state;\r
28         bh=rSjJAz3w8woYPeiPZ1rldRZ3luikkCzldglqMO0OrUo=;\r
29         b=Z4WfWnzhKHBjy87pLghqOYk+P79MrvcwRYakFmEnwSQ1iaeEobXLWe7nriXrrYcugn\r
30         +knmWo9C8roiH4kBuvkBk7M1KygftPQKE2lY5QVU3EELm69c2yuBjXRlZnVuu6wqFuma\r
31         Pu6iew3Ms0VfqR+OOaZRAdgBZXYiSDvl/ft+pkYiF7GtTY2LQ+qgvwt1/UPnlQTKMY71\r
32         dLOwEMf9u0XXx5NTwQpZMiJ2o1LQighRjeuBtPRE1pMNkN4qoO6Kx9rrP/sg5noXe1aq\r
33         Aek1c6SpffBN2TNSXKECly+YafSzZ9OqaRuprV7Iat0S91lbftIHw4k2EKWTkAj2xM1+\r
34         w/Sg==\r
35 Received: by 10.224.194.1 with SMTP id dw1mr14002459qab.87.1336466001685;\r
36         Tue, 08 May 2012 01:33:21 -0700 (PDT)\r
37 Received: from localhost (nikula.org. [92.243.24.172])\r
38         by mx.google.com with ESMTPS id hv18sm2806450qab.19.2012.05.08.01.33.18\r
39         (version=SSLv3 cipher=OTHER); Tue, 08 May 2012 01:33:20 -0700 (PDT)\r
40 From: Jani Nikula <jani@nikula.org>\r
41 To: Austin Clements <amdragon@MIT.EDU>, notmuch@notmuchmail.org\r
42 Subject: Re: [PATCH v2 2/2] new: Centralize file type stat-ing logic\r
43 In-Reply-To: <87r4uvdryz.fsf@nikula.org>\r
44 References: <1336414186-15293-1-git-send-email-amdragon@mit.edu>\r
45         <1336429240-1114-1-git-send-email-amdragon@mit.edu>\r
46         <1336429240-1114-3-git-send-email-amdragon@mit.edu>\r
47         <87r4uvdryz.fsf@nikula.org>\r
48 User-Agent: Notmuch/0.11.1+222~ga47a98c (http://notmuchmail.org) Emacs/23.1.1\r
49         (i686-pc-linux-gnu)\r
50 Date: Tue, 08 May 2012 08:33:16 +0000\r
51 Message-ID: <87obpzdqcz.fsf@nikula.org>\r
52 MIME-Version: 1.0\r
53 Content-Type: text/plain; charset=us-ascii\r
54 X-Gm-Message-State:\r
55  ALoCoQk2wZuM1mSaEBs4An72CY6ht4d4zqMAYpZDDf4mcqmw3Uncze4/YaXBItm9HgE9Qc8X4cXs\r
56 Cc: Vladimir Marek <vlmarek@volny.cz>\r
57 X-BeenThere: notmuch@notmuchmail.org\r
58 X-Mailman-Version: 2.1.13\r
59 Precedence: list\r
60 List-Id: "Use and development of the notmuch mail system."\r
61         <notmuch.notmuchmail.org>\r
62 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
63         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
64 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
65 List-Post: <mailto:notmuch@notmuchmail.org>\r
66 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
67 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
68         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
69 X-List-Received-Date: Tue, 08 May 2012 08:33:23 -0000\r
70 \r
71 On Tue, 08 May 2012 07:58:28 +0000, Jani Nikula <jani@nikula.org> wrote:\r
72 > On Mon,  7 May 2012 18:20:40 -0400, Austin Clements <amdragon@MIT.EDU> wrote:\r
73 > > This moves our logic to get a file's type into one function.  This has\r
74 > > several benefits: we can support OSes and file systems that do not\r
75 > > provide dirent.d_type or always return DT_UNKNOWN, complex\r
76 > > symlink-handling logic has been replaced by a simple stat fall-through\r
77 > > in one place, and the error message for un-stat-able file is more\r
78 > > accurate (previously, the error always mentioned directories, even\r
79 > > though a broken symlink is not a directory).\r
80\r
81 > LGTM.\r
82 \r
83 Okay, it's good, but I think you can make it even better:\r
84 \r
85 add_files_recursive() has check for "! S_ISDIR (st.st_mode)" in the\r
86 beginning, returning silently in case it recursed based on a symlink to\r
87 regular file. IIUC, this will no longer happen with your patch, as\r
88 symlinks are resolved and stat'ed before recursing.\r
89 \r
90 add_files() exists to fail loudly in the same situation, and has\r
91 otherwise the same checks in the beginning. I think you could now use\r
92 the checks from add_files() to replace the ones in\r
93 add_files_recursive(), and get rid of add_files() altogether.\r
94 \r
95 Please double check my thinking. Also this should probably be a separate\r
96 patch, no need to change the current one.\r
97 \r
98 Jani.\r
99 \r
100 \r
101\r
102 > > ---\r
103 > >  notmuch-new.c |  103 +++++++++++++++++++++++++++++++++++----------------------\r
104 > >  test/new      |    2 +-\r
105 > >  2 files changed, 64 insertions(+), 41 deletions(-)\r
106 > > \r
107 > > diff --git a/notmuch-new.c b/notmuch-new.c\r
108 > > index cb720cc..8955677 100644\r
109 > > --- a/notmuch-new.c\r
110 > > +++ b/notmuch-new.c\r
111 > > @@ -154,6 +154,48 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b)\r
112 > >      return strcmp ((*a)->d_name, (*b)->d_name);\r
113 > >  }\r
114 > >  \r
115 > > +/* Return the type of a directory entry relative to path as a stat(2)\r
116 > > + * mode.  Like stat, this follows symlinks.  Returns -1 and sets errno\r
117 > > + * if the file's type cannot be determined (which includes dangling\r
118 > > + * symlinks).\r
119 > > + */\r
120 > > +static int\r
121 > > +dirent_type (const char *path, const struct dirent *entry)\r
122 > > +{\r
123 > > +    struct stat statbuf;\r
124 > > +    char *abspath;\r
125 > > +    int err, saved_errno;\r
126 > > +\r
127 > > +#ifdef _DIRENT_HAVE_D_TYPE\r
128 > > +    /* Mapping from d_type to stat mode_t.  We omit DT_LNK so that\r
129 > > +     * we'll fall through to stat and get the real file type. */\r
130 > > +    static const mode_t modes[] = {\r
131 > > +   [DT_BLK]  = S_IFBLK,\r
132 > > +   [DT_CHR]  = S_IFCHR,\r
133 > > +   [DT_DIR]  = S_IFDIR,\r
134 > > +   [DT_FIFO] = S_IFIFO,\r
135 > > +   [DT_REG]  = S_IFREG,\r
136 > > +   [DT_SOCK] = S_IFSOCK\r
137 > > +    };\r
138 > > +    if (entry->d_type < ARRAY_SIZE(modes) && modes[entry->d_type])\r
139 > > +   return modes[entry->d_type];\r
140 > > +#endif\r
141 > > +\r
142 > > +    abspath = talloc_asprintf (NULL, "%s/%s", path, entry->d_name);\r
143 > > +    if (!abspath) {\r
144 > > +   errno = ENOMEM;\r
145 > > +   return -1;\r
146 > > +    }\r
147 > > +    err = stat(abspath, &statbuf);\r
148 > > +    saved_errno = errno;\r
149 > > +    talloc_free (abspath);\r
150 > > +    if (err < 0) {\r
151 > > +   errno = saved_errno;\r
152 > > +   return -1;\r
153 > > +    }\r
154 > > +    return statbuf.st_mode & S_IFMT;\r
155 > > +}\r
156 > > +\r
157 > >  /* Test if the directory looks like a Maildir directory.\r
158 > >   *\r
159 > >   * Search through the array of directory entries to see if we can find all\r
160 > > @@ -162,12 +204,12 @@ dirent_sort_strcmp_name (const struct dirent **a, const struct dirent **b)\r
161 > >   * Return 1 if the directory looks like a Maildir and 0 otherwise.\r
162 > >   */\r
163 > >  static int\r
164 > > -_entries_resemble_maildir (struct dirent **entries, int count)\r
165 > > +_entries_resemble_maildir (const char *path, struct dirent **entries, int count)\r
166 > >  {\r
167 > >      int i, found = 0;\r
168 > >  \r
169 > >      for (i = 0; i < count; i++) {\r
170 > > -   if (entries[i]->d_type != DT_DIR && entries[i]->d_type != DT_UNKNOWN)\r
171 > > +   if (dirent_type (path, entries[i]) != S_IFDIR)\r
172 > >         continue;\r
173 > >  \r
174 > >     if (strcmp(entries[i]->d_name, "new") == 0 ||\r
175 > > @@ -250,7 +292,7 @@ add_files_recursive (notmuch_database_t *notmuch,\r
176 > >      notmuch_status_t status, ret = NOTMUCH_STATUS_SUCCESS;\r
177 > >      notmuch_message_t *message = NULL;\r
178 > >      struct dirent **fs_entries = NULL;\r
179 > > -    int i, num_fs_entries;\r
180 > > +    int i, num_fs_entries, entry_type;\r
181 > >      notmuch_directory_t *directory;\r
182 > >      notmuch_filenames_t *db_files = NULL;\r
183 > >      notmuch_filenames_t *db_subdirs = NULL;\r
184 > > @@ -317,7 +359,7 @@ add_files_recursive (notmuch_database_t *notmuch,\r
185 > >      }\r
186 > >  \r
187 > >      /* Pass 1: Recurse into all sub-directories. */\r
188 > > -    is_maildir = _entries_resemble_maildir (fs_entries, num_fs_entries);\r
189 > > +    is_maildir = _entries_resemble_maildir (path, fs_entries, num_fs_entries);\r
190 > >  \r
191 > >      for (i = 0; i < num_fs_entries; i++) {\r
192 > >     if (interrupted)\r
193 > > @@ -325,17 +367,16 @@ add_files_recursive (notmuch_database_t *notmuch,\r
194 > >  \r
195 > >     entry = fs_entries[i];\r
196 > >  \r
197 > > -   /* We only want to descend into directories.\r
198 > > -    * But symlinks can be to directories too, of course.\r
199 > > -    *\r
200 > > -    * And if the filesystem doesn't tell us the file type in the\r
201 > > -    * scandir results, then it might be a directory (and if not,\r
202 > > -    * then we'll stat and return immediately in the next level of\r
203 > > -    * recursion). */\r
204 > > -   if (entry->d_type != DT_DIR &&\r
205 > > -       entry->d_type != DT_LNK &&\r
206 > > -       entry->d_type != DT_UNKNOWN)\r
207 > > -   {\r
208 > > +   /* We only want to descend into directories (and symlinks to\r
209 > > +    * directories). */\r
210 > > +   entry_type = dirent_type (path, entry);\r
211 > > +   if (entry_type == -1) {\r
212 > > +       /* Be pessimistic, e.g. so we don't lose lots of mail just\r
213 > > +        * because a user broke a symlink. */\r
214 > > +       fprintf (stderr, "Error reading file %s/%s: %s\n",\r
215 > > +                path, entry->d_name, strerror (errno));\r
216 > > +       return NOTMUCH_STATUS_FILE_ERROR;\r
217 > > +   } else if (entry_type != S_IFDIR) {\r
218 > >         continue;\r
219 > >     }\r
220 > >  \r
221 > > @@ -425,31 +466,13 @@ add_files_recursive (notmuch_database_t *notmuch,\r
222 > >         notmuch_filenames_move_to_next (db_subdirs);\r
223 > >     }\r
224 > >  \r
225 > > -   /* If we're looking at a symlink, we only want to add it if it\r
226 > > -    * links to a regular file, (and not to a directory, say).\r
227 > > -    *\r
228 > > -    * Similarly, if the file is of unknown type (due to filesystem\r
229 > > -    * limitations), then we also need to look closer.\r
230 > > -    *\r
231 > > -    * In either case, a stat does the trick.\r
232 > > -    */\r
233 > > -   if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) {\r
234 > > -       int err;\r
235 > > -\r
236 > > -       next = talloc_asprintf (notmuch, "%s/%s", path, entry->d_name);\r
237 > > -       err = stat (next, &st);\r
238 > > -       talloc_free (next);\r
239 > > -       next = NULL;\r
240 > > -\r
241 > > -       /* Don't emit an error for a link pointing nowhere, since\r
242 > > -        * the directory-traversal pass will have already done\r
243 > > -        * that. */\r
244 > > -       if (err)\r
245 > > -           continue;\r
246 > > -\r
247 > > -       if (! S_ISREG (st.st_mode))\r
248 > > -           continue;\r
249 > > -   } else if (entry->d_type != DT_REG) {\r
250 > > +   /* Only add regular files (and symlinks to regular files). */\r
251 > > +   entry_type = dirent_type (path, entry);\r
252 > > +   if (entry_type == -1) {\r
253 > > +       fprintf (stderr, "Error reading file %s/%s: %s\n",\r
254 > > +                path, entry->d_name, strerror (errno));\r
255 > > +       return NOTMUCH_STATUS_FILE_ERROR;\r
256 > > +   } else if (entry_type != S_IFREG) {\r
257 > >         continue;\r
258 > >     }\r
259 > >  \r
260 > > diff --git a/test/new b/test/new\r
261 > > index 26253db..e3900f5 100755\r
262 > > --- a/test/new\r
263 > > +++ b/test/new\r
264 > > @@ -140,7 +140,7 @@ test_begin_subtest "Broken symlink aborts"\r
265 > >  ln -s does-not-exist "${MAIL_DIR}/broken"\r
266 > >  output=$(NOTMUCH_NEW 2>&1)\r
267 > >  test_expect_equal "$output" \\r
268 > > -"Error reading directory /run/shm/nm/tmp.new/mail/broken: No such file or directory\r
269 > > +"Error reading file /run/shm/nm/tmp.new/mail/broken: No such file or directory\r
270 > >  Note: A fatal error was encountered: Something went wrong trying to read or write a file\r
271 > >  No new mail."\r
272 > >  rm "${MAIL_DIR}/broken"\r
273 > > -- \r
274 > > 1.7.10\r
275 > > \r
276 > > _______________________________________________\r
277 > > notmuch mailing list\r
278 > > notmuch@notmuchmail.org\r
279 > > http://notmuchmail.org/mailman/listinfo/notmuch\r