Commit 720c9b75 720c9b75ad87d0e02a8a387ea74b1e9741facce7 by Sergey Poznyakoff

Allow to set mailbox permissions using fileinto Sieve action.

* mailbox/permstr.c: New file.
* mailbox/Makefile.am (libmailutils_la_SOURCES): Add permstr.c.
* imap4d/imap4d.c (parse_mode_spec): Remove function.
(cb_mailbox_mode): Use mu_parse_stream_perm_string instead of
parse_mode_spec.
* imap4d/imap4d.h (namespace_getfullpath)
(namespace_checkfullpath): First arg is const.
* imap4d/namespace.c (namespace_getfullpath)
(namespace_checkfullpath): First arg is const.
* include/mailutils/message.h (mu_message_save_to_mailbox): Add
5th argument (permissions).
* mailbox/message.c: Likewise.
* include/mailutils/mutil.h (mu_parse_stream_perm_string): New
proto.
(mu_stream_flags_to_mode): Add isdir argument.
* libsieve/actions.c (sieve_action_fileinto): New tag :permissions
allows to set permissions to the mailbox being created.
* mailbox/mutil.c (mu_stream_flags_to_mode): Add 2nd argument
(isdir). Any bits in [go] sets imply raising 'x' bit for
directories (i.e. if isdir != 0).

* libproto/maildir/mbox.c, mailbox/amd.c: Update calls to
mu_stream_flags_to_mode.

* NEWS, doc/texinfo/sieve.texi: Update.

Allow to set file permissions of the local mailboxes during
creation.
1 2008-11-07 Sergey Poznyakoff <gray@gnu.org.ua> 1 2008-11-07 Sergey Poznyakoff <gray@gnu.org.ua>
2 2
3 Allow to set mailbox permissions using fileinto Sieve action.
4
5 * mailbox/permstr.c: New file.
6 * mailbox/Makefile.am (libmailutils_la_SOURCES): Add permstr.c.
7 * imap4d/imap4d.c (parse_mode_spec): Remove function.
8 (cb_mailbox_mode): Use mu_parse_stream_perm_string instead of
9 parse_mode_spec.
10 * imap4d/imap4d.h (namespace_getfullpath)
11 (namespace_checkfullpath): First arg is const.
12 * imap4d/namespace.c (namespace_getfullpath)
13 (namespace_checkfullpath): First arg is const.
14 * include/mailutils/message.h (mu_message_save_to_mailbox): Add
15 5th argument (permissions).
16 * mailbox/message.c: Likewise.
17 * include/mailutils/mutil.h (mu_parse_stream_perm_string): New
18 proto.
19 (mu_stream_flags_to_mode): Add isdir argument.
20 * libsieve/actions.c (sieve_action_fileinto): New tag :permissions
21 allows to set permissions to the mailbox being created.
22 * mailbox/mutil.c (mu_stream_flags_to_mode): Add 2nd argument
23 (isdir). Any bits in [go] sets imply raising 'x' bit for
24 directories (i.e. if isdir != 0).
25
26 * libproto/maildir/mbox.c, mailbox/amd.c: Update calls to
27 mu_stream_flags_to_mode.
28
29 * NEWS, doc/texinfo/sieve.texi: Update.
30
3 Allow to set file permissions of the local mailboxes during 31 Allow to set file permissions of the local mailboxes during
4 creation. 32 creation.
5 33
......
1 GNU mailutils NEWS -- history of user-visible changes. 2008-10-23 1 GNU mailutils NEWS -- history of user-visible changes. 2008-11-07
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007,
3 2008 Free Software Foundation, Inc. 3 2008 Free Software Foundation, Inc.
4 See the end of file for copying conditions. 4 See the end of file for copying conditions.
...@@ -61,7 +61,9 @@ message', below. ...@@ -61,7 +61,9 @@ message', below.
61 The communication protocol has been modified to make this possible. 61 The communication protocol has been modified to make this possible.
62 The traditional comsat protocol is supported as well. 62 The traditional comsat protocol is supported as well.
63 63
64 ** New Sieve action `pipe' 64 ** Sieve
65
66 *** New Sieve action `pipe'
65 67
66 Syntax: pipe [:envelope] <command line: string> 68 Syntax: pipe [:envelope] <command line: string>
67 69
...@@ -69,6 +71,18 @@ This action executes the given <command line> and pipes the message to ...@@ -69,6 +71,18 @@ This action executes the given <command line> and pipes the message to
69 its standard input. If the :envelope tag is given, the envelope of the 71 its standard input. If the :envelope tag is given, the envelope of the
70 message is piped as well. 72 message is piped as well.
71 73
74 *** Fileinto :permissions
75
76 The `fileinto' action takes a tag :permissions that allows to set
77 permissions on the mailbox, in case it is created. Its argument is a
78 string, similar to that used in chmod(1):
79
80 [go](+|=)[rw]
81
82 For example:
83
84 fileinto :permissions "g=rw,o=r" "/shared/mailbox"
85
72 ** Client SMTP STARTTLS support 86 ** Client SMTP STARTTLS support
73 87
74 ** Support for new protocols: POPS (pops://) and IMAPS (imaps://), 88 ** Support for new protocols: POPS (pops://) and IMAPS (imaps://),
......
1 @c This is part of the GNU Mailutils manual. 1 @c This is part of the GNU Mailutils manual.
2 @c Copyright (C) 1999,2000,2001,2002,2003,2004, 2 @c Copyright (C) 1999,2000,2001,2002,2003,2004,
3 @c 2007 Free Software Foundation, Inc. 3 @c 2007, 2008 Free Software Foundation, Inc.
4 @c See file mailutils.texi for copying conditions. 4 @c See file mailutils.texi for copying conditions.
5 @comment ******************************************************************* 5 @comment *******************************************************************
6 6
...@@ -929,7 +929,7 @@ if header :contains ["from"] ["idiot@@example.edu"] ...@@ -929,7 +929,7 @@ if header :contains ["from"] ["idiot@@example.edu"]
929 @end smallexample 929 @end smallexample
930 @end deffn 930 @end deffn
931 931
932 @deffn Action fileinto @var{folder} 932 @deffn Action fileinto [:permissions @var{mode}] @var{folder}
933 @noindent 933 @noindent
934 934
935 Required arguments: 935 Required arguments:
...@@ -939,7 +939,74 @@ Required arguments: ...@@ -939,7 +939,74 @@ Required arguments:
939 A string representing the folder name 939 A string representing the folder name
940 @end table 940 @end table
941 941
942 The @code{fileinto} action delivers the message into the specified folder. 942 @noindent
943 Tagged arguments:
944
945 @table @code
946 @item :permissions @var{mode}
947 Specifies the permissions to use, if the mailbox is created.
948 @end table
949
950 The @code{fileinto} action delivers the message into the specified
951 folder. If the folder is local, it is created using permissions
952 @samp{0600}, for regular files, and @samp{0700} for directories. This
953 default can be changed by using the @code{:permissions} tag. Its
954 argument is a mode specification, similar to that used by
955 @command{chmod} shell utility. It is a list of permissions settings
956 separated by commas. Each setting begins with one of the following
957 letters:
958
959 @table @asis
960 @item g
961 Set permissions for the users in the file group.
962
963 @item o
964 Set permissions for users not in the file's group.
965 @end table
966
967 This letter must be followed by either @samp{+} or @samp{=} and the
968 list of permissions to be set. This latter list is a string
969 containing any one or both of the following characters:
970
971 @table @asis
972 @item r
973 Grant permission to read.
974
975 @item w
976 Grant permission to write.
977 @end table
978
979 For example, the following instruction creates the mailbox
980 @file{~/shared} which will be world readable and writable
981 for the group:
982
983 @smallexample
984 fileinto :permissions "g=rw,o=r" "~/shared"
985 @end smallexample
986
987 Notice that:
988
989 @enumerate 1
990 @item
991 The @code{:permissions} setting are affected by the current umask
992 value.
993
994 @item
995 Only @code{r} and @code{w} permissions can be set, since other
996 permissions do not seem to be useful for mailboxes. However, for
997 mailboxes that have a directory structure (such as maildir and MH),
998 any settings in @samp{g} and @samp{o} sets imply setting the
999 executable bit.
1000
1001 @item
1002 Owner's permissions cannot be set. The owner always has all
1003 permissions on the mailbox he created.
1004
1005 @item
1006 The @code{:permissions} settings apply only to local mailboxes. They
1007 are ignored for remote mailboxes.
1008 @end enumerate
1009
943 @end deffn 1010 @end deffn
944 1011
945 @deffn Action reject @var{reason} 1012 @deffn Action reject @var{reason}
......
...@@ -284,101 +284,13 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val) ...@@ -284,101 +284,13 @@ cb_preauth (mu_debug_t debug, void *data, mu_config_value_t *val)
284 return 0; 284 return 0;
285 } 285 }
286 286
287 #define FILE_MODE_READ 0x1
288 #define FILE_MODE_WRITE 0x2
289
290 static int
291 parse_mode_bits (int *pmode, const char *str, const char **endp)
292 {
293 switch (*str)
294 {
295 case '+':
296 case '=':
297 str++;
298 break;
299
300 default:
301 *endp = str;
302 return 1;
303 }
304
305 for (; *str; str++)
306 {
307 switch (*str)
308 {
309 case 'r':
310 *pmode |= FILE_MODE_READ;
311 break;
312
313 case 'w':
314 *pmode |= FILE_MODE_WRITE;
315 break;
316
317 case ',':
318 *endp = str;
319 return 0;
320
321 default:
322 *endp = str;
323 return 1;
324 }
325 }
326 *endp = str;
327 return 0;
328 }
329
330 static int
331 parse_mode_spec (int *pmode, const char *str, const char **endp)
332 {
333 int mode = 0;
334 int f;
335 while (*str)
336 {
337 switch (*str)
338 {
339 case 'g':
340 if (parse_mode_bits (&f, str + 1, &str))
341 {
342 *endp = str;
343 return 1;
344 }
345 if (f & FILE_MODE_READ)
346 mode |= MU_STREAM_IRGRP;
347 if (f & FILE_MODE_WRITE)
348 mode |= MU_STREAM_IWGRP;
349 break;
350
351 case 'o':
352 if (parse_mode_bits (&f, str + 1, &str))
353 {
354 *endp = str;
355 return 1;
356 }
357 if (f & FILE_MODE_READ)
358 mode |= MU_STREAM_IROTH;
359 if (f & FILE_MODE_WRITE)
360 mode |= MU_STREAM_IWOTH;
361 break;
362
363 default:
364 *endp = str;
365 return 1;
366 }
367 if (*str == ',')
368 str++;
369 }
370 *pmode = mode;
371 *endp = str;
372 return 0;
373 }
374
375 static int 287 static int
376 cb_mailbox_mode (mu_debug_t debug, void *data, mu_config_value_t *val) 288 cb_mailbox_mode (mu_debug_t debug, void *data, mu_config_value_t *val)
377 { 289 {
378 char *p; 290 const char *p;
379 if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug)) 291 if (mu_cfg_assert_value_type (val, MU_CFG_STRING, debug))
380 return 1; 292 return 1;
381 if (parse_mode_spec ((int *)data, val->v.string, &p)) 293 if (mu_parse_stream_perm_string ((int *)data, val->v.string, &p))
382 mu_cfg_format_error (debug, MU_DEBUG_ERROR, 294 mu_cfg_format_error (debug, MU_DEBUG_ERROR,
383 _("invalid mode string near %s"), p); 295 _("invalid mode string near %s"), p);
384 return 0; 296 return 0;
......
...@@ -283,8 +283,9 @@ extern mu_list_t namespace[NS_MAX]; ...@@ -283,8 +283,9 @@ extern mu_list_t namespace[NS_MAX];
283 283
284 extern int namespace_init_session (char *path); 284 extern int namespace_init_session (char *path);
285 extern void namespace_init (void); 285 extern void namespace_init (void);
286 extern char *namespace_getfullpath (char *name, const char *delim, int *pns); 286 extern char *namespace_getfullpath (const char *name, const char *delim,
287 extern char *namespace_checkfullpath (char *name, const char *pattern, 287 int *pns);
288 extern char *namespace_checkfullpath (const char *name, const char *pattern,
288 const char *delim, int *pns); 289 const char *delim, int *pns);
289 int imap4d_session_setup (char *username); 290 int imap4d_session_setup (char *username);
290 int imap4d_session_setup0 (void); 291 int imap4d_session_setup0 (void);
......
...@@ -166,11 +166,12 @@ risky_pattern (const char *pattern, int delim) ...@@ -166,11 +166,12 @@ risky_pattern (const char *pattern, int delim)
166 } 166 }
167 167
168 char * 168 char *
169 namespace_checkfullpath (char *name, const char *pattern, const char *delim, 169 namespace_checkfullpath (const char *name, const char *pattern,
170 int *nspace) 170 const char *delim, int *nspace)
171 { 171 {
172 struct namespace_info info; 172 struct namespace_info info;
173 char *p, *path = NULL; 173 const char *p;
174 char *path = NULL;
174 char *scheme = NULL; 175 char *scheme = NULL;
175 176
176 p = strchr (name, ':'); 177 p = strchr (name, ':');
...@@ -226,17 +227,18 @@ namespace_checkfullpath (char *name, const char *pattern, const char *delim, ...@@ -226,17 +227,18 @@ namespace_checkfullpath (char *name, const char *pattern, const char *delim,
226 } 227 }
227 228
228 char * 229 char *
229 namespace_getfullpath (char *name, const char *delim, int *nspace) 230 namespace_getfullpath (const char *name, const char *delim, int *nspace)
230 { 231 {
232 char *ret;
231 if (strcasecmp (name, "INBOX") == 0 && auth_data->change_uid) 233 if (strcasecmp (name, "INBOX") == 0 && auth_data->change_uid)
232 { 234 {
233 name = strdup (auth_data->mailbox); 235 ret = strdup (auth_data->mailbox);
234 if (nspace) 236 if (nspace)
235 *nspace = NS_PRIVATE; 237 *nspace = NS_PRIVATE;
236 } 238 }
237 else 239 else
238 name = namespace_checkfullpath (name, NULL, delim, nspace); 240 ret = namespace_checkfullpath (name, NULL, delim, nspace);
239 return name; 241 return ret;
240 } 242 }
241 243
242 int 244 int
......
...@@ -124,7 +124,8 @@ extern int mu_message_get_attachment_name (mu_message_t, char *name, ...@@ -124,7 +124,8 @@ extern int mu_message_get_attachment_name (mu_message_t, char *name,
124 extern int mu_message_aget_attachment_name (mu_message_t, char **name); 124 extern int mu_message_aget_attachment_name (mu_message_t, char **name);
125 125
126 extern int mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, 126 extern int mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket,
127 mu_debug_t debug, const char *toname); 127 mu_debug_t debug, const char *toname,
128 int perms);
128 129
129 130
130 extern int mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg); 131 extern int mu_stream_to_message (mu_stream_t instream, mu_message_t *pmsg);
......
...@@ -155,8 +155,11 @@ extern size_t mu_strftime (char *s, size_t max, const char *format, ...@@ -155,8 +155,11 @@ extern size_t mu_strftime (char *s, size_t max, const char *format,
155 extern int mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab, 155 extern int mutil_parse_field_map (const char *map, mu_assoc_t *passoc_tab,
156 int *perr); 156 int *perr);
157 157
158 extern int mu_stream_flags_to_mode (int flags); 158 extern int mu_stream_flags_to_mode (int flags, int isdir);
159 159
160 extern int mu_parse_stream_perm_string (int *pmode, const char *str,
161 const char **endp);
162
160 163
161 #ifdef __cplusplus 164 #ifdef __cplusplus
162 } 165 }
......
...@@ -435,7 +435,8 @@ maildir_create (struct _amd_data *amd, int flags) ...@@ -435,7 +435,8 @@ maildir_create (struct _amd_data *amd, int flags)
435 char *tmpname = maildir_mkfilename (amd->name, dirs[i], NULL); 435 char *tmpname = maildir_mkfilename (amd->name, dirs[i], NULL);
436 int rc = maildir_opendir (&dir, tmpname, 436 int rc = maildir_opendir (&dir, tmpname,
437 PERMS | 437 PERMS |
438 mu_stream_flags_to_mode (amd->mailbox->flags)); 438 mu_stream_flags_to_mode (amd->mailbox->flags,
439 1));
439 if (rc) 440 if (rc)
440 return rc; 441 return rc;
441 closedir (dir); 442 closedir (dir);
...@@ -528,7 +529,8 @@ maildir_flush (struct _amd_data *amd) ...@@ -528,7 +529,8 @@ maildir_flush (struct _amd_data *amd)
528 char *tmpname = maildir_mkfilename (amd->name, TMPSUF, NULL); 529 char *tmpname = maildir_mkfilename (amd->name, TMPSUF, NULL);
529 530
530 rc = maildir_opendir (&dir, tmpname, 531 rc = maildir_opendir (&dir, tmpname,
531 PERMS | mu_stream_flags_to_mode (amd->mailbox->flags)); 532 PERMS |
533 mu_stream_flags_to_mode (amd->mailbox->flags, 1));
532 if (rc) 534 if (rc)
533 { 535 {
534 free (tmpname); 536 free (tmpname);
...@@ -668,7 +670,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, ...@@ -668,7 +670,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED,
668 name = maildir_mkfilename (amd->name, NEWSUF, NULL); 670 name = maildir_mkfilename (amd->name, NEWSUF, NULL);
669 671
670 status = maildir_opendir (&dir, name, 672 status = maildir_opendir (&dir, name,
671 PERMS | mu_stream_flags_to_mode (mailbox->flags)); 673 PERMS |
674 mu_stream_flags_to_mode (mailbox->flags, 1));
672 if (status == 0) 675 if (status == 0)
673 { 676 {
674 maildir_deliver_new (amd, dir); 677 maildir_deliver_new (amd, dir);
...@@ -679,7 +682,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED, ...@@ -679,7 +682,8 @@ maildir_scan0 (mu_mailbox_t mailbox, size_t msgno MU_ARG_UNUSED,
679 name = maildir_mkfilename (amd->name, CURSUF, NULL); 682 name = maildir_mkfilename (amd->name, CURSUF, NULL);
680 /* 3rd phase: Scan cur/ */ 683 /* 3rd phase: Scan cur/ */
681 status = maildir_opendir (&dir, name, 684 status = maildir_opendir (&dir, name,
682 PERMS | mu_stream_flags_to_mode (mailbox->flags)); 685 PERMS |
686 mu_stream_flags_to_mode (mailbox->flags, 1));
683 if (status == 0) 687 if (status == 0)
684 { 688 {
685 status = maildir_scan_dir (amd, dir, CURSUF); 689 status = maildir_scan_dir (amd, dir, CURSUF);
......
...@@ -79,19 +79,34 @@ static int ...@@ -79,19 +79,34 @@ static int
79 sieve_action_fileinto (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags) 79 sieve_action_fileinto (mu_sieve_machine_t mach, mu_list_t args, mu_list_t tags)
80 { 80 {
81 int rc; 81 int rc;
82 int mbflags = 0;
83 mu_sieve_value_t *opt;
82 mu_sieve_value_t *val = mu_sieve_value_get (args, 0); 84 mu_sieve_value_t *val = mu_sieve_value_get (args, 0);
83 if (!val) 85 if (!val)
84 { 86 {
85 mu_sieve_error (mach, _("cannot get filename!")); 87 mu_sieve_error (mach, _("cannot get filename!"));
86 mu_sieve_abort (mach); 88 mu_sieve_abort (mach);
87 } 89 }
90
91 if (mu_sieve_tag_lookup (tags, "permissions", &opt))
92 {
93 const char *p;
94
95 if (mu_parse_stream_perm_string (&mbflags, opt->v.string, &p))
96 {
97 /* Should not happen, but anyway... */
98 mu_sieve_error (mach, _("invalid permissions (near %s)"), p);
99 return 1;
100 }
101 }
102
88 mu_sieve_log_action (mach, "FILEINTO", 103 mu_sieve_log_action (mach, "FILEINTO",
89 _("delivering into %s"), val->v.string); 104 _("delivering into %s"), val->v.string);
90 if (mu_sieve_is_dry_run (mach)) 105 if (mu_sieve_is_dry_run (mach))
91 return 0; 106 return 0;
92 107
93 rc = mu_message_save_to_mailbox (mach->msg, mach->ticket, mach->debug, 108 rc = mu_message_save_to_mailbox (mach->msg, mach->ticket, mach->debug,
94 val->v.string); 109 val->v.string, mbflags);
95 if (rc) 110 if (rc)
96 mu_sieve_error (mach, _("cannot save to mailbox: %s"), 111 mu_sieve_error (mach, _("cannot save to mailbox: %s"),
97 mu_strerror (rc)); 112 mu_strerror (rc));
...@@ -506,17 +521,57 @@ mu_sieve_data_type fileinto_args[] = { ...@@ -506,17 +521,57 @@ mu_sieve_data_type fileinto_args[] = {
506 SVT_VOID 521 SVT_VOID
507 }; 522 };
508 523
524 static int
525 perms_tag_checker (const char *name, mu_list_t tags, mu_list_t args)
526 {
527 mu_iterator_t itr;
528 int err = 0;
529
530 if (!tags || mu_list_get_iterator (tags, &itr))
531 return 0;
532 for (mu_iterator_first (itr); !err && !mu_iterator_is_done (itr);
533 mu_iterator_next (itr))
534 {
535 int flag;
536 char *p;
537 mu_sieve_runtime_tag_t *t;
538 mu_iterator_current (itr, (void **)&t);
539 if (strcmp (t->tag, "permissions") == 0)
540 {
541 if (mu_parse_stream_perm_string (&flag, t->arg->v.string, &p))
542 {
543 mu_sv_compile_error (&mu_sieve_locus,
544 _("invalid permissions (near %s)"), p);
545 err = 1;
546 }
547 }
548 }
549 mu_iterator_destroy (&itr);
550 return err;
551 }
552
553 static mu_sieve_tag_def_t perms_tags[] = {
554 { "permissions", SVT_STRING },
555 { NULL }
556 };
557
558 static mu_sieve_tag_group_t fileinto_tag_groups[] = {
559 { perms_tags, perms_tag_checker },
560 { NULL }
561 };
562
509 void 563 void
510 mu_sv_register_standard_actions (mu_sieve_machine_t mach) 564 mu_sv_register_standard_actions (mu_sieve_machine_t mach)
511 { 565 {
512 mu_sieve_register_action (mach, "stop", sieve_action_stop, NULL, NULL, 1); 566 mu_sieve_register_action (mach, "stop", sieve_action_stop, NULL, NULL, 1);
513 mu_sieve_register_action (mach, "keep", sieve_action_keep, NULL, NULL, 1); 567 mu_sieve_register_action (mach, "keep", sieve_action_keep, NULL, NULL, 1);
514 mu_sieve_register_action (mach, "discard", sieve_action_discard, NULL, NULL, 1); 568 mu_sieve_register_action (mach, "discard", sieve_action_discard,
569 NULL, NULL, 1);
515 mu_sieve_register_action (mach, "fileinto", sieve_action_fileinto, 570 mu_sieve_register_action (mach, "fileinto", sieve_action_fileinto,
516 fileinto_args, NULL, 0); 571 fileinto_args, fileinto_tag_groups, 0);
517 mu_sieve_register_action (mach, "reject", sieve_action_reject, fileinto_args, 572 mu_sieve_register_action (mach, "reject", sieve_action_reject, fileinto_args,
518 NULL, 0); 573 NULL, 0);
519 mu_sieve_register_action (mach, "redirect", sieve_action_redirect, 574 mu_sieve_register_action (mach, "redirect", sieve_action_redirect,
520 fileinto_args, NULL, 0); 575 fileinto_args, NULL, 0);
521 } 576 }
522 577
......
...@@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \ ...@@ -108,6 +108,7 @@ libmailutils_la_SOURCES = \
108 opool.c\ 108 opool.c\
109 parse822.c\ 109 parse822.c\
110 parsedate.c\ 110 parsedate.c\
111 permstr.c\
111 progmailer.c\ 112 progmailer.c\
112 property.c\ 113 property.c\
113 registrar.c\ 114 registrar.c\
......
...@@ -336,9 +336,8 @@ amd_open (mu_mailbox_t mailbox, int flags) ...@@ -336,9 +336,8 @@ amd_open (mu_mailbox_t mailbox, int flags)
336 if ((flags & MU_STREAM_CREAT) && errno == ENOENT) 336 if ((flags & MU_STREAM_CREAT) && errno == ENOENT)
337 { 337 {
338 int rc; 338 int rc;
339 339 int perms = mu_stream_flags_to_mode (flags, 1);
340 if (mkdir (amd->name, 340 if (mkdir (amd->name, S_IRUSR|S_IWUSR|S_IXUSR|perms))
341 S_IRUSR|S_IWUSR|S_IXUSR|mu_stream_flags_to_mode (flags)))
342 return errno; 341 return errno;
343 if (stat (amd->name, &st) < 0) 342 if (stat (amd->name, &st) < 0)
344 return errno; 343 return errno;
......
...@@ -488,7 +488,7 @@ _file_open (mu_stream_t stream) ...@@ -488,7 +488,7 @@ _file_open (mu_stream_t stream)
488 return errno; 488 return errno;
489 /* Race condition here when creating the file ??. */ 489 /* Race condition here when creating the file ??. */
490 fd = open (filename, flg|O_CREAT|O_EXCL, 490 fd = open (filename, flg|O_CREAT|O_EXCL,
491 0600 | mu_stream_flags_to_mode (flags)); 491 0600 | mu_stream_flags_to_mode (flags, 0));
492 if (fd < 0) 492 if (fd < 0)
493 return errno; 493 return errno;
494 } 494 }
......
...@@ -1112,7 +1112,7 @@ message_body_read (mu_stream_t stream, char *buffer, size_t n, mu_off_t off, ...@@ -1112,7 +1112,7 @@ message_body_read (mu_stream_t stream, char *buffer, size_t n, mu_off_t off,
1112 int 1112 int
1113 mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, 1113 mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket,
1114 mu_debug_t debug, 1114 mu_debug_t debug,
1115 const char *toname) 1115 const char *toname, int perms)
1116 { 1116 {
1117 int rc = 0; 1117 int rc = 0;
1118 mu_mailbox_t to = 0; 1118 mu_mailbox_t to = 0;
...@@ -1148,7 +1148,9 @@ mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket, ...@@ -1148,7 +1148,9 @@ mu_message_save_to_mailbox (mu_message_t msg, mu_ticket_t ticket,
1148 } 1148 }
1149 } 1149 }
1150 1150
1151 if ((rc = mu_mailbox_open (to, MU_STREAM_WRITE | MU_STREAM_CREAT))) 1151 if ((rc = mu_mailbox_open (to,
1152 MU_STREAM_WRITE | MU_STREAM_CREAT
1153 | (perms & MU_STREAM_IMASK))))
1152 { 1154 {
1153 MU_DEBUG2 (debug, MU_DEBUG_ERROR, 1155 MU_DEBUG2 (debug, MU_DEBUG_ERROR,
1154 "mu_mailbox_open (%s) failed: %s\n", toname, 1156 "mu_mailbox_open (%s) failed: %s\n", toname,
......
...@@ -1491,7 +1491,7 @@ mu_sql_decode_password_type (const char *arg, enum mu_password_type *t) ...@@ -1491,7 +1491,7 @@ mu_sql_decode_password_type (const char *arg, enum mu_password_type *t)
1491 } 1491 }
1492 1492
1493 int 1493 int
1494 mu_stream_flags_to_mode (int flags) 1494 mu_stream_flags_to_mode (int flags, int isdir)
1495 { 1495 {
1496 int mode = 0; 1496 int mode = 0;
1497 if (flags & MU_STREAM_IRGRP) 1497 if (flags & MU_STREAM_IRGRP)
...@@ -1502,5 +1502,14 @@ mu_stream_flags_to_mode (int flags) ...@@ -1502,5 +1502,14 @@ mu_stream_flags_to_mode (int flags)
1502 mode |= S_IROTH; 1502 mode |= S_IROTH;
1503 if (flags & MU_STREAM_IWOTH) 1503 if (flags & MU_STREAM_IWOTH)
1504 mode |= S_IWOTH; 1504 mode |= S_IWOTH;
1505
1506 if (isdir)
1507 {
1508 if (mode & (S_IRGRP|S_IWGRP))
1509 mode |= S_IXGRP;
1510 if (mode & (S_IROTH|S_IWOTH))
1511 mode |= S_IXOTH;
1512 }
1513
1505 return mode; 1514 return mode;
1506 } 1515 }
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2008 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library; if not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301 USA */
18
19 #if HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 #include <mailutils/stream.h>
23 #include <mailutils/mutil.h>
24 #include <mailutils/errno.h>
25
26 #define FILE_PERM_READ 0x1
27 #define FILE_PERM_WRITE 0x2
28
29 static int
30 parse_perm_bits (int *pmode, const char *str, const char **endp)
31 {
32 switch (*str)
33 {
34 case '+':
35 case '=':
36 str++;
37 break;
38
39 default:
40 if (endp)
41 *endp = str;
42 return 1;
43 }
44
45 for (; *str; str++)
46 {
47 switch (*str)
48 {
49 case 'r':
50 *pmode |= FILE_PERM_READ;
51 break;
52
53 case 'w':
54 *pmode |= FILE_PERM_WRITE;
55 break;
56
57 case ',':
58 if (endp)
59 *endp = str;
60 return 0;
61
62 default:
63 if (endp)
64 *endp = str;
65 return 1;
66 }
67 }
68 if (endp)
69 *endp = str;
70 return 0;
71 }
72
73 /* Parse a MU stream permission specification in form:
74
75 g(+|=)[wr]+,o(+|=)[wr]+
76
77 Return 0 on success.
78 On failure, return MU_ERR_FAILURE and point endp to the offending character.
79 */
80 int
81 mu_parse_stream_perm_string (int *pmode, const char *str, const char **endp)
82 {
83 int mode = 0;
84 int f;
85 while (*str)
86 {
87 switch (*str)
88 {
89 case 'g':
90 if (parse_perm_bits (&f, str + 1, &str))
91 {
92 if (endp)
93 *endp = str;
94 return MU_ERR_FAILURE;
95 }
96 if (f & FILE_PERM_READ)
97 mode |= MU_STREAM_IRGRP;
98 if (f & FILE_PERM_WRITE)
99 mode |= MU_STREAM_IWGRP;
100 break;
101
102 case 'o':
103 if (parse_perm_bits (&f, str + 1, &str))
104 {
105 if (endp)
106 *endp = str;
107 return MU_ERR_FAILURE;
108 }
109 if (f & FILE_PERM_READ)
110 mode |= MU_STREAM_IROTH;
111 if (f & FILE_PERM_WRITE)
112 mode |= MU_STREAM_IWOTH;
113 break;
114
115 default:
116 if (endp)
117 *endp = str;
118 return MU_ERR_FAILURE;
119 }
120 if (*str == ',')
121 str++;
122 }
123 *pmode = mode;
124 if (endp)
125 *endp = str;
126 return 0;
127 }
128