X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/8e669ac162fe3b1040297f1d021de10778dce9d9..0a49a7a4f1090b6f1ce1d0f9d969804c9226b53e:/src/src/transports/appendfile.c diff --git a/src/src/transports/appendfile.c b/src/src/transports/appendfile.c index 27e87cf0b..df2ce1cd8 100644 --- a/src/src/transports/appendfile.c +++ b/src/src/transports/appendfile.c @@ -1,10 +1,10 @@ -/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.5 2005/02/17 11:58:27 ph10 Exp $ */ +/* $Cambridge: exim/src/src/transports/appendfile.c,v 1.24 2009/11/16 19:50:39 nm4 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2005 */ +/* Copyright (c) University of Cambridge 1995 - 2009 */ /* See the file NOTICE for conditions of use and distribution. */ @@ -107,6 +107,8 @@ optionlist appendfile_transport_options[] = { (void *)offsetof(appendfile_transport_options_block, maildir_tag) }, { "maildir_use_size_file", opt_bool, (void *)offsetof(appendfile_transport_options_block, maildir_use_size_file ) } , + { "maildirfolder_create_regex", opt_stringptr, + (void *)offsetof(appendfile_transport_options_block, maildirfolder_create_regex ) }, #endif /* SUPPORT_MAILDIR */ #ifdef SUPPORT_MAILSTORE { "mailstore_format", opt_bool, @@ -184,16 +186,17 @@ appendfile_transport_options_block appendfile_transport_option_defaults = { NULL, /* mailbox_filecount_string */ US"^(?:cur|new|\\..*)$", /* maildir_dir_regex */ NULL, /* maildir_tag */ + NULL, /* maildirfolder_create_regex */ NULL, /* mailstore_prefix */ NULL, /* mailstore_suffix */ NULL, /* check_string (default changed for non-bsmtp file)*/ NULL, /* escape_string (ditto) */ NULL, /* file_format */ + 0, /* quota_value */ + 0, /* quota_warn_threshold_value */ -1, /* mailbox_size_value */ -1, /* mailbox_filecount_value */ - 0, /* quota_value */ 0, /* quota_filecount_value */ - 0, /* quota_warn_threshold_value */ APPENDFILE_MODE, /* mode */ APPENDFILE_DIRECTORY_MODE, /* dirmode */ APPENDFILE_LOCKFILE_MODE, /* lockfile_mode */ @@ -247,6 +250,8 @@ Arguments: tblock points to the transport instance addrlist addresses about to be delivered (not used) dummy not used (doesn't pass back data) + uid the uid that will be set (not used) + gid the gid that will be set (not used) errmsg where to put an error message Returns: OK, FAIL, or DEFER @@ -254,26 +259,29 @@ Returns: OK, FAIL, or DEFER static int appendfile_transport_setup(transport_instance *tblock, address_item *addrlist, - transport_feedback *dummy, uschar **errmsg) + transport_feedback *dummy, uid_t uid, gid_t gid, uschar **errmsg) { appendfile_transport_options_block *ob = (appendfile_transport_options_block *)(tblock->options_block); uschar *q = ob->quota; -int *v = &(ob->quota_value); -int default_value = 0; +double default_value = 0.0; int i; addrlist = addrlist; /* Keep picky compilers happy */ dummy = dummy; +uid = uid; +gid = gid; /* Loop for quota, quota_filecount, quota_warn_threshold, mailbox_size, mailbox_filecount */ for (i = 0; i < 5; i++) { - if (q == NULL) *v = default_value; else + double d; + uschar *which = NULL; + + if (q == NULL) d = default_value; else { - double d; uschar *rest; uschar *s = expand_string(q); @@ -286,12 +294,13 @@ for (i = 0; i < 5; i++) d = Ustrtod(s, &rest); - /* Handle following characters K, M, %, the latter being permitted + /* Handle following characters K, M, G, %, the latter being permitted for quota_warn_threshold only. A threshold with no quota setting is just ignored. */ if (tolower(*rest) == 'k') { d *= 1024.0; rest++; } else if (tolower(*rest) == 'm') { d *= 1024.0*1024.0; rest++; } + else if (tolower(*rest) == 'g') { d *= 1024.0*1024.0*1024.0; rest++; } else if (*rest == '%' && i == 2) { if (ob->quota_value <= 0 && !ob->maildir_use_size_file) d = 0; @@ -313,33 +322,51 @@ for (i = 0; i < 5; i++) "in %s transport", s, q, tblock->name); return FAIL; } - - *v = (int)d; } + /* Set each value, checking for possible overflow. */ + switch (i) { case 0: + if (d >= 2.0*1024.0*1024.0*1024.0 && sizeof(off_t) <= 4) which = US"quota"; + ob->quota_value = (off_t)d; q = ob->quota_filecount; - v = &(ob->quota_filecount_value); break; case 1: + if (d >= 2.0*1024.0*1024.0*1024.0) which = US"quota_filecount"; + ob->quota_filecount_value = (int)d; q = ob->quota_warn_threshold; - v = &(ob->quota_warn_threshold_value); break; case 2: + if (d >= 2.0*1024.0*1024.0*1024.0 && sizeof(off_t) <= 4) + which = US"quota_warn_threshold"; + ob->quota_warn_threshold_value = (off_t)d; q = ob->mailbox_size_string; - v = &(ob->mailbox_size_value); - default_value = -1; + default_value = -1.0; break; case 3: + if (d >= 2.0*1024.0*1024.0*1024.0 && sizeof(off_t) <= 4) + which = US"mailbox_size";; + ob->mailbox_size_value = (off_t)d; q = ob->mailbox_filecount_string; - v = &(ob->mailbox_filecount_value); + break; + + case 4: + if (d >= 2.0*1024.0*1024.0*1024.0) which = US"mailbox_filecount"; + ob->mailbox_filecount_value = (int)d; break; } + + if (which != NULL) + { + *errmsg = string_sprintf("%s value %.10g is too large (overflow) in " + "%s transport", which, d, tblock->name); + return FAIL; + } } return OK; @@ -547,7 +574,7 @@ Returns: nothing */ static void -notify_comsat(uschar *user, int offset) +notify_comsat(uschar *user, off_t offset) { struct servent *sp; host_item host; @@ -556,7 +583,7 @@ uschar buffer[256]; DEBUG(D_transport) debug_printf("notify_comsat called\n"); -sprintf(CS buffer, "%.200s@%d\n", user, offset); +sprintf(CS buffer, "%.200s@" OFF_T_FMT "\n", user, offset); if ((sp = getservbyname("biff", "udp")) == NULL) { @@ -572,10 +599,10 @@ host.next = NULL; until one succeeds. However, it appears that at least on some systems, comsat doesn't listen on the ::1 address. So for the moment, just force the address to be 127.0.0.1. At some future stage, when IPv6 really is superseding IPv4, this -can be changed. */ +can be changed. (But actually, comsat is probably dying out anyway.) */ /****** -if (host_find_byname(&host, NULL, NULL, FALSE) == HOST_FIND_FAILED) +if (host_find_byname(&host, NULL, 0, NULL, FALSE) == HOST_FIND_FAILED) { DEBUG(D_transport) debug_printf("\"localhost\" unknown\n"); return; @@ -599,7 +626,7 @@ for (h = &host; h != NULL; h = h->next) (void)ip_connect(sock, host_af, h->address, ntohs(sp->s_port), 0); rc = send(sock, buffer, Ustrlen(buffer) + 1, 0); - close(sock); + (void)close(sock); if (rc >= 0) break; DEBUG(D_transport) @@ -704,11 +731,11 @@ Returns: the sum of the sizes of the stattable files zero if the directory cannot be opened */ -int +off_t check_dir_size(uschar *dirname, int *countptr, const pcre *regex) { DIR *dir; -int sum = 0; +off_t sum = 0; int count = *countptr; struct dirent *ent; struct stat statbuf; @@ -733,12 +760,13 @@ while ((ent = readdir(dir)) != NULL) if (pcre_exec(regex, NULL, CS name, Ustrlen(name), 0, 0, ovector,6) >= 2) { uschar *endptr; - int size = Ustrtol(name + ovector[2], &endptr, 10); + off_t size = (off_t)Ustrtod(name + ovector[2], &endptr); if (endptr == name + ovector[3]) { sum += size; DEBUG(D_transport) - debug_printf("check_dir_size: size from %s is %d\n", name, size); + debug_printf("check_dir_size: size from %s is " OFF_T_FMT "\n", name, + size); continue; } } @@ -772,7 +800,9 @@ while ((ent = readdir(dir)) != NULL) closedir(dir); DEBUG(D_transport) - debug_printf("check_dir_size: dir=%s sum=%d count=%d\n", dirname, sum, count); + debug_printf("check_dir_size: dir=%s sum=" OFF_T_FMT " count=%d\n", dirname, + sum, count); + *countptr = count; return sum; } @@ -874,9 +904,10 @@ Returns: OK if all went well, DEFER otherwise, with errno preserved #define MBX_NUSERFLAGS 30 static int -copy_mbx_message(int to_fd, int from_fd, int saved_size) +copy_mbx_message(int to_fd, int from_fd, off_t saved_size) { -int used, size; +int used; +off_t size; struct stat statbuf; /* If the current mailbox size is zero, write a header block */ @@ -902,8 +933,8 @@ size, including CRLFs, which is the size of the input (temporary) file. */ if (fstat(from_fd, &statbuf) < 0) return DEFER; size = statbuf.st_size; -sprintf (CS deliver_out_buffer, "%s,%lu;%08lx%04x-%08x\015\012", - tod_stamp(tod_mbx), (long unsigned int)size, 0L, 0, 0); +sprintf (CS deliver_out_buffer, "%s," OFF_T_FMT ";%08lx%04x-%08x\015\012", + tod_stamp(tod_mbx), size, 0L, 0, 0); used = Ustrlen(deliver_out_buffer); /* Rewind the temporary file, and copy it over in chunks. */ @@ -1198,6 +1229,7 @@ uschar *filecount_msg = US""; uschar *path; struct utimbuf times; struct timeval msg_tv; +BOOL disable_quota = FALSE; BOOL isdirectory = FALSE; BOOL isfifo = FALSE; BOOL wait_for_tick = FALSE; @@ -1205,8 +1237,8 @@ uid_t uid = geteuid(); /* See note above */ gid_t gid = getegid(); int mbformat; int mode = (addr->mode > 0)? addr->mode : ob->mode; -int saved_size = -1; -int mailbox_size = ob->mailbox_size_value; +off_t saved_size = -1; +off_t mailbox_size = ob->mailbox_size_value; int mailbox_filecount = ob->mailbox_filecount_value; int hd = -1; int fd = -1; @@ -1305,10 +1337,15 @@ if (path[0] != '/') return FALSE; } -/* For a file delivery, make sure the local part in the address is updated to -the true local part. */ +/* For a file delivery, make sure the local part in the address(es) is updated +to the true local part. */ -if (testflag(addr, af_file)) addr->local_part = string_copy(path); +if (testflag(addr, af_file)) + { + address_item *addr2; + for (addr2 = addr; addr2 != NULL; addr2 = addr2->next) + addr2->local_part = string_copy(path); + } /* The available mailbox formats depend on whether it is a directory or a file delivery. */ @@ -1335,10 +1372,12 @@ else DEBUG(D_transport) { - debug_printf("appendfile: mode=%o notify_comsat=%d quota=%d warning=%d%s\n" + debug_printf("appendfile: mode=%o notify_comsat=%d quota=" OFF_T_FMT + " warning=" OFF_T_FMT "%s\n" " %s=%s format=%s\n message_prefix=%s\n message_suffix=%s\n " "maildir_use_size_file=%s\n", - mode, ob->notify_comsat, ob->quota_value, ob->quota_warn_threshold_value, + mode, ob->notify_comsat, ob->quota_value, + ob->quota_warn_threshold_value, ob->quota_warn_threshold_is_percent? "%" : "", isdirectory? "directory" : "file", path, mailbox_formats[mbformat], @@ -1421,7 +1460,7 @@ if (!isdirectory) if (cfd >= 0) { transport_instance *tt = check_file_format(cfd, tblock, addr); - close(cfd); + (void)close(cfd); /* If another transport is indicated, call it and return; if no transport was found, just return - the error data will have been set up.*/ @@ -1613,7 +1652,7 @@ if (!isdirectory) sufficiently worried. */ if ((rc = Ulink(hitchname, lockname)) != 0) fstat(hd, &statbuf); - close(hd); + (void)close(hd); Uunlink(hitchname); if (rc != 0 && statbuf.st_nlink != 2) { @@ -1725,8 +1764,8 @@ if (!isdirectory) /* We have successfully created and opened the file. Ensure that the group and the mode are correct. */ - Uchown(filename, uid, gid); - Uchmod(filename, mode); + (void)Uchown(filename, uid, gid); + (void)Uchmod(filename, mode); } @@ -1984,7 +2023,7 @@ if (!isdirectory) } } - mbx_lockfd = Uopen(mbx_lockname, O_RDWR | O_CREAT, 0600); + mbx_lockfd = Uopen(mbx_lockname, O_RDWR | O_CREAT, ob->lockfile_mode); if (mbx_lockfd < 0) { addr->basic_errno = ERRNO_LOCKFAILED; @@ -1993,7 +2032,7 @@ if (!isdirectory) goto RETURN; } - Uchmod(mbx_lockname, 0600); + (void)Uchmod(mbx_lockname, ob->lockfile_mode); if (apply_lock(mbx_lockfd, F_WRLCK, ob->use_fcntl, ob->lock_fcntl_timeout, ob->use_flock, ob->lock_flock_timeout) >= 0) @@ -2014,7 +2053,7 @@ if (!isdirectory) DEBUG(D_transport) debug_printf("failed to lock %s: %s\n", mbx_lockname, strerror(errno)); - close(mbx_lockfd); + (void)close(mbx_lockfd); mbx_lockfd = -1; } else @@ -2030,7 +2069,7 @@ if (!isdirectory) DEBUG(D_transport) debug_printf("fcntl(), flock(), or MBX locking failed - retrying\n"); - close(fd); + (void)close(fd); fd = -1; use_lstat = TRUE; /* Reset to use lstat first */ @@ -2116,10 +2155,11 @@ else } #ifdef SUPPORT_MAILDIR - /* For a maildir delivery, ensure that all the relevant directories exist */ + /* For a maildir delivery, ensure that all the relevant directories exist, + and a maildirfolder file if necessary. */ if (mbformat == mbf_maildir && !maildir_ensure_directories(path, addr, - ob->create_directory, ob->dirmode)) + ob->create_directory, ob->dirmode, ob->maildirfolder_create_regex)) return FALSE; #endif /* SUPPORT_MAILDIR */ @@ -2135,7 +2175,7 @@ else const uschar *error; int offset; - /* Compile the regex if there is one */ + /* Compile the regex if there is one. */ if (ob->quota_size_regex != NULL) { @@ -2148,11 +2188,8 @@ else ob->quota_size_regex); return FALSE; } - else - { - DEBUG(D_transport) debug_printf("using regex for file sizes: %s\n", - ob->quota_size_regex); - } + DEBUG(D_transport) debug_printf("using regex for file sizes: %s\n", + ob->quota_size_regex); } /* Use an explicitly configured directory if set */ @@ -2203,6 +2240,8 @@ else { *slash = 0; check_path = new_check_path; + DEBUG(D_transport) debug_printf("maildirfolder file exists: " + "quota check directory changed to %s\n", check_path); } } } @@ -2228,6 +2267,8 @@ else if (ob->maildir_dir_regex != NULL) { + int check_path_len = Ustrlen(check_path); + dir_regex = pcre_compile(CS ob->maildir_dir_regex, PCRE_COPT, (const char **)&error, &offset, NULL); if (dir_regex == NULL) @@ -2237,11 +2278,27 @@ else ob->maildir_dir_regex); return FALSE; } - else + + DEBUG(D_transport) + debug_printf("using regex for maildir directory selection: %s\n", + ob->maildir_dir_regex); + + /* Check to see if we are delivering into an ignored directory, that is, + if the delivery path starts with the quota check path, and the rest + of the deliver path matches the regex; if so, set a flag to disable quota + checking and maildirsize updating. */ + + if (Ustrncmp(path, check_path, check_path_len) == 0) { - DEBUG(D_transport) - debug_printf("using regex for maildir directory selection: %s\n", - ob->maildir_dir_regex); + uschar *s = path + check_path_len; + while (*s == '/') s++; + s = (*s == 0)? US "new" : string_sprintf("%s/new", s); + if (pcre_exec(dir_regex, NULL, CS s, Ustrlen(s), 0, 0, NULL, 0) < 0) + { + disable_quota = TRUE; + DEBUG(D_transport) debug_printf("delivery directory does not match " + "maildir_quota_directory_regex: disabling quota\n"); + } } } @@ -2252,8 +2309,10 @@ else /* if (???? || ob->quota_value > 0) */ + if (!disable_quota) { - int size, filecount; + off_t size; + int filecount; maildirsize_fd = maildir_ensure_sizefile(check_path, ob, regex, dir_regex, &size, &filecount); @@ -2286,15 +2345,17 @@ else } #endif /* SUPPORT_MAILDIR */ - /* Otherwise (mailbox_size is not yet set), if we are going to do a quota - check later on, find the current size of the mailbox. (We don't need to check - ob->quota_filecount_value, because it can only be set if ob->quota_value is - set.) */ + /* Otherwise if we are going to do a quota check later on, and the mailbox + size is not set, find the current size of the mailbox. Ditto for the file + count. Note that ob->quota_filecount_value cannot be set without + ob->quota_value being set. */ - if ((mailbox_size < 0 || mailbox_filecount < 0) && - (ob->quota_value > 0 || THRESHOLD_CHECK)) + if (!disable_quota && + (ob->quota_value > 0 || THRESHOLD_CHECK) && + (mailbox_size < 0 || + (mailbox_filecount < 0 && ob->quota_filecount_value > 0))) { - int size; + off_t size; int filecount = 0; DEBUG(D_transport) debug_printf("quota checks on directory %s\n", check_path); @@ -2390,6 +2451,8 @@ else addr->message = string_sprintf ("failed to open %s (%d tr%s)", filename, i, (i == 1)? "y" : "ies"); addr->basic_errno = errno; + if (errno == errno_quota || errno == ENOSPC) + addr->user_message = US"mailbox is full"; return FALSE; } @@ -2405,8 +2468,8 @@ else /* Why are these here? Put in because they are present in the non-maildir directory case above. */ - Uchown(filename, uid, gid); - Uchmod(filename, mode); + (void)Uchown(filename, uid, gid); + (void)Uchmod(filename, mode); } #endif /* SUPPORT_MAILDIR */ @@ -2447,8 +2510,8 @@ else /* Why are these here? Put in because they are present in the non-maildir directory case above. */ - Uchown(filename, uid, gid); - Uchmod(filename, mode); + (void)Uchown(filename, uid, gid); + (void)Uchmod(filename, mode); /* Built a C stream from the open file descriptor. */ @@ -2458,7 +2521,7 @@ else addr->transport_return = PANIC; addr->message = string_sprintf("fdopen of %s (" "for %s transport) failed", filename, tblock->name); - close(fd); + (void)close(fd); Uunlink(filename); return FALSE; } @@ -2476,7 +2539,7 @@ else addr->message = string_sprintf("Expansion of \"%s\" (mailstore " "prefix for %s transport) failed: %s", ob->mailstore_prefix, tblock->name, expand_string_message); - fclose(env_file); + (void)fclose(env_file); Uunlink(filename); return FALSE; } @@ -2505,7 +2568,7 @@ else addr->message = string_sprintf("Expansion of \"%s\" (mailstore " "suffix for %s transport) failed: %s", ob->mailstore_suffix, tblock->name, expand_string_message); - fclose(env_file); + (void)fclose(env_file); Uunlink(filename); return FALSE; } @@ -2539,8 +2602,8 @@ else Uunlink(filename); return FALSE; } - Uchown(dataname, uid, gid); - Uchmod(dataname, mode); + (void)Uchown(dataname, uid, gid); + (void)Uchmod(dataname, mode); } #endif /* SUPPORT_MAILSTORE */ @@ -2549,8 +2612,8 @@ else /* In all cases of writing to a new file, ensure that the file which is going to be renamed has the correct ownership and mode. */ - Uchown(filename, uid, gid); - Uchmod(filename, mode); + (void)Uchown(filename, uid, gid); + (void)Uchmod(filename, mode); } @@ -2568,12 +2631,13 @@ with this message if quota_is_inclusive is set; if it is not set, the check is for the mailbox already being over quota (i.e. the current message is not included in the check). */ -if (ob->quota_value > 0) +if (!disable_quota && ob->quota_value > 0) { DEBUG(D_transport) { - debug_printf("Exim quota = %d old size = %d this message = %d " - "(%sincluded)\n", ob->quota_value, mailbox_size, message_size, + debug_printf("Exim quota = " OFF_T_FMT " old size = " OFF_T_FMT + " this message = %d (%sincluded)\n", + ob->quota_value, mailbox_size, message_size, ob->quota_is_inclusive? "" : "not "); debug_printf(" file count quota = %d count = %d\n", ob->quota_filecount_value, mailbox_filecount); @@ -2721,7 +2785,7 @@ if (temp_file != NULL && ob->mbx_format) /* Preserve errno while closing the temporary file. */ mbx_save_errno = errno; - fclose(temp_file); + (void)fclose(temp_file); errno = mbx_save_errno; } #endif /* SUPPORT_MBX */ @@ -2729,7 +2793,7 @@ if (temp_file != NULL && ob->mbx_format) /* Force out the remaining data to check for any errors; some OS don't allow fsync() to be called for a FIFO. */ -if (yield == OK && !isfifo && fsync(fd) < 0) yield = DEFER; +if (yield == OK && !isfifo && EXIMfsync(fd) < 0) yield = DEFER; /* Update message_size to the accurate count of bytes written, including added headers. */ @@ -2737,29 +2801,36 @@ added headers. */ message_size = transport_count; /* If using a maildir++ quota file, add this message's size to it, and -close the file descriptor. */ +close the file descriptor, except when the quota has been disabled because we +are delivering into an uncounted folder. */ #ifdef SUPPORT_MAILDIR -if (yield == OK && maildirsize_fd >= 0) - maildir_record_length(maildirsize_fd, message_size); - -maildir_save_errno = errno; /* Preserve errno while closing the file */ -close(maildirsize_fd); -errno = maildir_save_errno; +if (!disable_quota) + { + if (yield == OK && maildirsize_fd >= 0) + maildir_record_length(maildirsize_fd, message_size); + maildir_save_errno = errno; /* Preserve errno while closing the file */ + (void)close(maildirsize_fd); + errno = maildir_save_errno; + } #endif /* SUPPORT_MAILDIR */ /* If there is a quota warning threshold and we are have crossed it with this message, set the SPECIAL_WARN flag in the address, to cause a warning message to be sent. */ -if (THRESHOLD_CHECK) +if (!disable_quota && THRESHOLD_CHECK) { - int threshold = ob->quota_warn_threshold_value; + off_t threshold = ob->quota_warn_threshold_value; if (ob->quota_warn_threshold_is_percent) - threshold = (int)(((double)ob->quota_value * threshold) / 100); + threshold = (off_t)(((double)ob->quota_value * threshold) / 100); DEBUG(D_transport) - debug_printf("quota = %d threshold = %d old size = %d message size = %d\n", - ob->quota_value, threshold, mailbox_size, message_size); + debug_printf("quota = " OFF_T_FMT + " threshold = " OFF_T_FMT + " old size = " OFF_T_FMT + " message size = %d\n", + ob->quota_value, threshold, mailbox_size, + message_size); if (mailbox_size <= threshold && mailbox_size + message_size > threshold) addr->special_action = SPECIAL_WARN; @@ -2834,6 +2905,7 @@ if (yield != OK) #else addr->message = string_sprintf("mailbox is full"); #endif /* EDQUOT */ + addr->user_message = US"mailbox is full"; DEBUG(D_transport) debug_printf("System quota exceeded for %s%s%s\n", dataname, isdirectory? US"" : US": time since file read = ", @@ -2904,7 +2976,7 @@ if (yield != OK) investigated so far have ftruncate(), whereas not all have the F_FREESP fcntl() call (BSDI & FreeBSD do not). */ - if (!isdirectory) ftruncate(fd, saved_size); + if (!isdirectory) (void)ftruncate(fd, saved_size); } /* Handle successful writing - we want the modification time to be now for @@ -3115,7 +3187,7 @@ if (mbx_lockfd >= 0) debug_printf("unlinking MBX lock file %s\n", mbx_lockname); Uunlink(mbx_lockname); } - close(mbx_lockfd); + (void)close(mbx_lockfd); } #endif /* SUPPORT_MBX */