/* XXX - these two functions should be out in append.c or reserve.c * or something more general */ EXPORTED const char *dlist_reserve_path(const char *part, int isarchive, const struct message_guid *guid) { static char buf[MAX_MAILBOX_PATH]; const char *base; /* part can be either a configured partition name, or a path */ if (strchr(part, '/')) { base = part; } else { base = isarchive ? config_archivepartitiondir(part) : config_partitiondir(part); } /* we expect to have a base at this point, so let's assert that */ assert(base != NULL); snprintf(buf, MAX_MAILBOX_PATH, "%s/sync./%lu/%s", base, (unsigned long)getpid(), message_guid_encode(guid)); /* gotta make sure we can create files */ if (cyrus_mkdir(buf, 0755)) { /* it's going to fail later, but at least this will help */ syslog(LOG_ERR, "IOERROR: failed to create %s/sync./%lu/ for reserve: %m", base, (unsigned long)getpid()); } return buf; }
static int myopen(const char *fname, int flags, struct dbengine **ret, struct txn **mytid) { struct dbengine *db; struct stat sbuf; assert(fname && ret); db = find_db(fname); if (db) goto out; /* new reference to existing db */ db = (struct dbengine *) xzmalloc(sizeof(struct dbengine)); db->fd = open(fname, O_RDWR, 0644); if (db->fd == -1 && errno == ENOENT) { if (!(flags & CYRUSDB_CREATE)) { free_db(db); return CYRUSDB_NOTFOUND; } if (cyrus_mkdir(fname, 0755) == -1) { free_db(db); return CYRUSDB_IOERROR; } db->fd = open(fname, O_RDWR | O_CREAT, 0644); } if (db->fd == -1) { syslog(LOG_ERR, "IOERROR: opening %s: %m", fname); free_db(db); return CYRUSDB_IOERROR; } if (fstat(db->fd, &sbuf) == -1) { syslog(LOG_ERR, "IOERROR: fstat on %s: %m", fname); close(db->fd); free_db(db); return CYRUSDB_IOERROR; } db->ino = sbuf.st_ino; map_refresh(db->fd, 0, &db->base, &db->len, sbuf.st_size, fname, 0); db->size = sbuf.st_size; db->fname = xstrdup(fname); db->refcount = 1; /* prepend to the list */ db->next = alldbs; alldbs = db; if (mytid) { int r = starttxn_or_refetch(db, mytid); if (r) return r; } out: *ret = db; return 0; }
static void sync_log_base(const char *channel, const char *string) { int fd; struct stat sbuffile, sbuffd; int retries = 0; const char *fname; /* are we being supressed? */ if (!sync_log_enabled(channel)) return; fname = sync_log_fname(channel); while (retries++ < SYNC_LOG_RETRIES) { fd = open(fname, O_WRONLY|O_APPEND|O_CREAT, 0640); if (fd < 0 && errno == ENOENT) { if (!cyrus_mkdir(fname, 0755)) { fd = open(fname, O_WRONLY|O_APPEND|O_CREAT, 0640); } } if (fd < 0) { syslog(LOG_ERR, "sync_log(): Unable to write to log file %s: %s", fname, strerror(errno)); return; } if (lock_blocking(fd, fname) == -1) { syslog(LOG_ERR, "sync_log(): Failed to lock %s for %s: %m", fname, string); xclose(fd); return; } /* Check that the file wasn't renamed after it was opened above */ if ((fstat(fd, &sbuffd) == 0) && (stat(fname, &sbuffile) == 0) && (sbuffd.st_ino == sbuffile.st_ino)) break; lock_unlock(fd, fname); xclose(fd); } if (retries >= SYNC_LOG_RETRIES) { xclose(fd); syslog(LOG_ERR, "sync_log(): Failed to lock %s for %s after %d attempts", fname, string, retries); return; } if (retry_write(fd, string, strlen(string)) < 0) syslog(LOG_ERR, "write() to %s failed: %s", fname, strerror(errno)); (void)fsync(fd); /* paranoia */ lock_unlock(fd, fname); xclose(fd); }
/* NOTE - we don't provide any guarantees that the file isn't open multiple * times. So don't do that. It will mess with your locking no end */ EXPORTED int mappedfile_open(struct mappedfile **mfp, const char *fname, int flags) { struct mappedfile *mf; struct stat sbuf; int openmode = (flags & MAPPEDFILE_RW) ? O_RDWR : O_RDONLY; int create = (flags & MAPPEDFILE_CREATE) ? 1 : 0; int r; assert(fname); assert(!*mfp); mf = xzmalloc(sizeof(struct mappedfile)); mf->fname = xstrdup(fname); mf->is_rw = (flags & MAPPEDFILE_RW) ? 1 : 0; mf->fd = open(mf->fname, openmode, 0644); if (mf->fd < 0 && errno == ENOENT) { if (!create || !mf->is_rw) { r = -errno; goto err; } r = cyrus_mkdir(mf->fname, 0755); if (r < 0) { syslog(LOG_ERR, "IOERROR: cyrus_mkdir %s: %m", mf->fname); goto err; } mf->fd = open(mf->fname, O_RDWR | O_CREAT, 0644); } if (mf->fd == -1) { syslog(LOG_ERR, "IOERROR: open %s: %m", mf->fname); r = -errno; goto err; } /* it's zero, but set it anyway */ mf->lock_status = MF_UNLOCKED; mf->dirty = 0; r = fstat(mf->fd, &sbuf); if (r < 0) { syslog(LOG_ERR, "IOERROR: fstat %s: %m", mf->fname); goto err; } _ensure_mapped(mf, sbuf.st_size, /*update*/0); *mfp = mf; return 0; err: mappedfile_close(&mf); return r; }
static int my_mkparentdir(const char *fname) { struct buf buf = BUF_INITIALIZER; int r; buf_setcstr(&buf, fname); r = cyrus_mkdir(buf_cstring(&buf), 0755); buf_free(&buf); return r; }
EXPORTED int proc_register(const char *servicename, const char *clienthost, const char *userid, const char *mailbox) { pid_t pid = getpid(); FILE *procfile = NULL; char *newfname = NULL; if (!procfname) procfname = proc_getpath(pid, /*isnew*/0); newfname = proc_getpath(pid, /*isnew*/1); procfile = fopen(newfname, "w+"); if (!procfile) { if (cyrus_mkdir(newfname, 0755) == -1) { fatal("couldn't create proc directory", EC_IOERR); } else { syslog(LOG_NOTICE, "created proc directory"); procfile = fopen(newfname, "w+"); if (!procfile) { syslog(LOG_ERR, "IOERROR: creating %s: %m", newfname); fatal("can't write proc file", EC_IOERR); } } } fprintf(procfile, "%s\t%s", servicename, clienthost); if (userid) { fprintf(procfile, "\t%s", userid); if (mailbox) { fprintf(procfile, "\t%s", mailbox); } } putc('\n', procfile); fclose(procfile); if (rename(newfname, procfname)) { syslog(LOG_ERR, "IOERROR: renaming %s to %s: %m", newfname, procfname); unlink(newfname); fatal("can't write proc file", EC_IOERR); } setproctitle("%s: %s %s %s", servicename, clienthost, userid ? userid : "", mailbox ? mailbox : ""); free(newfname); return 0; }
int actions_setuser(const char *userid) { char userbuf[1024], *user, *domain = NULL; size_t size = 1024, len; int result; char *sieve_dir = (char *) xzmalloc(size+1); sieved_userid = xstrdup(userid); user = (char *) userid; if (config_virtdomains && strchr(user, '@')) { /* split the user and domain */ strlcpy(userbuf, userid, sizeof(userbuf)); user = userbuf; if ((domain = strrchr(user, '@'))) *domain++ = '\0'; } len = strlcpy(sieve_dir, sieve_dir_config, size); if (domain) { char dhash = (char) dir_hash_c(domain, config_fulldirhash); len += snprintf(sieve_dir+len, size-len, "%s%c/%s", FNAME_DOMAINDIR, dhash, domain); } if (sieved_userisadmin) { strlcat(sieve_dir, "/global", size); } else { char hash = (char) dir_hash_c(user, config_fulldirhash); snprintf(sieve_dir+len, size-len, "/%c/%s", hash, user); } result = chdir(sieve_dir); if (result != 0) { result = cyrus_mkdir(sieve_dir, 0755); if (!result) result = mkdir(sieve_dir, 0755); if (!result) result = chdir(sieve_dir); if (result) { syslog(LOG_ERR, "mkdir %s: %m", sieve_dir); free(sieve_dir); return TIMSIEVE_FAIL; } } free(sieve_dir); return TIMSIEVE_OK; }
int seen_open(const char *user, int flags, struct seen **seendbptr) { struct seen *seendb = NULL; char *fname = NULL; int dbflags = (flags & SEEN_CREATE) ? CYRUSDB_CREATE : 0; int r; assert(user); assert(*seendbptr == NULL); /* create seendb */ seendb = (struct seen *) xmalloc(sizeof(struct seen)); if (SEEN_DEBUG) { syslog(LOG_DEBUG, "seen_db: seen_open(%s)", user); } /* open the seendb corresponding to user */ fname = seen_getpath(user); if (flags & SEEN_CREATE) cyrus_mkdir(fname, 0755); r = cyrusdb_open(DB, fname, dbflags, &seendb->db); if (r) { if (!(flags & SEEN_SILENT)) { int level = (flags & SEEN_CREATE) ? LOG_ERR : LOG_DEBUG; syslog(level, "DBERROR: opening %s: %s", fname, cyrusdb_strerror(r)); } r = IMAP_IOERROR; free(seendb); free(fname); return r; } syslog(LOG_DEBUG, "seen_db: user %s opened %s", user, fname); free(fname); seendb->tid = NULL; seendb->user = xstrdup(user); *seendbptr = seendb; return r; }
/** * \brief Fills partition data. * * @param inout part_list items list structure * @param in idx item index */ static void partition_filldata(partlist_t *part_list, int idx) { partitem_t *item = &part_list->items[idx]; struct statvfs stat; item->id = 0; item->available = 0; item->total = 0; item->quota = 0.; if (statvfs(item->value, &stat)) { /* statvfs error */ int error = 1; if (errno == ENOENT) { /* try to create path */ if ((cyrus_mkdir(item->value, 0755) == -1) || (mkdir(item->value, 0755) == -1)) { syslog(LOG_ERR, "IOERROR: creating %s: %m", item->value); return; } else { error = statvfs(item->value, &stat) ? 1 : 0; } } if (error) { syslog(LOG_ERR, "IOERROR: statvfs[%s]: %m", item->value); return; } } if (stat.f_blocks <= 0) { /* error retrieving statvfs info */ syslog(LOG_ERR, "IOERROR: statvfs[%s]: non-positive number of blocks", item->value); return; } item->id = stat.f_fsid; item->available = (uint64_t)(stat.f_bavail * (stat.f_frsize / 1024.)); item->total = (uint64_t)(stat.f_blocks * (stat.f_frsize / 1024.)); }
int seen_rename_user(const char *olduser, const char *newuser) { char *oldfname = seen_getpath(olduser); char *newfname = seen_getpath(newuser); int r = 0; if (SEEN_DEBUG) { syslog(LOG_DEBUG, "seen_db: seen_rename_user(%s, %s)", olduser, newuser); } cyrus_mkdir(newfname, 0755); if (rename(oldfname, newfname) && errno != ENOENT) { syslog(LOG_ERR, "error renaming %s to %s: %m", oldfname, newfname); r = IMAP_IOERROR; } free(oldfname); free(newfname); return r; }
static int autocreate_sieve(const char *userid, const char *source_script) { /* XXX - this is really ugly, but too much work to tidy up right now -- Bron */ sieve_script_t *s = NULL; bytecode_info_t *bc = NULL; char *err = NULL; FILE *in_stream, *out_fp; int out_fd, in_fd, r, k; int do_compile = 0; const char *compiled_source_script = NULL; const char *sievename = get_script_name(source_script); const char *sieve_script_dir = NULL; char sieve_script_name[MAX_FILENAME]; char sieve_bcscript_name[MAX_FILENAME]; char sieve_default[MAX_FILENAME]; char sieve_tmpname[MAX_FILENAME]; char sieve_bctmpname[MAX_FILENAME]; char sieve_bclink_name[MAX_FILENAME]; char buf[4096]; mode_t oldmask; struct stat statbuf; /* We don't support using the homedirectory, like timsieved */ if (config_getswitch(IMAPOPT_SIEVEUSEHOMEDIR)) { syslog(LOG_WARNING,"autocreate_sieve: autocreate_sieve does not work with sieveusehomedir option in imapd.conf"); return 1; } /* Check if sievedir is defined in imapd.conf */ if(!config_getstring(IMAPOPT_SIEVEDIR)) { syslog(LOG_WARNING, "autocreate_sieve: sievedir option is not defined. Check imapd.conf"); return 1; } /* Check if autocreate_sieve_compiledscript is defined in imapd.conf */ if(!(compiled_source_script = config_getstring(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT_COMPILED))) { syslog(LOG_WARNING, "autocreate_sieve: autocreate_sieve_compiledscript option is not defined. Compiling it"); do_compile = 1; } if (!(sieve_script_dir = user_sieve_path(userid))) { syslog(LOG_WARNING, "autocreate_sieve: unable to determine sieve directory for user %s", userid); return 1; } if(snprintf(sieve_tmpname, MAX_FILENAME, "%s/%s.script.NEW",sieve_script_dir, sievename) >= MAX_FILENAME) { syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid); return 1; } if(snprintf(sieve_bctmpname, MAX_FILENAME, "%s/%s.bc.NEW",sieve_script_dir, sievename) >= MAX_FILENAME) { syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid); return 1; } if(snprintf(sieve_script_name, MAX_FILENAME, "%s/%s.script",sieve_script_dir, sievename) >= MAX_FILENAME) { syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid); return 1; } if(snprintf(sieve_bcscript_name, MAX_FILENAME, "%s/%s.bc",sieve_script_dir, sievename) >= MAX_FILENAME) { syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid); return 1; } if(snprintf(sieve_default, MAX_FILENAME, "%s/%s",sieve_script_dir,"defaultbc") >= MAX_FILENAME) { syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid); return 1; } /* XXX no directory? umm */ if(snprintf(sieve_bclink_name, MAX_FILENAME, "%s.bc", sievename) >= MAX_FILENAME) { syslog(LOG_WARNING, "autocreate_sieve: Invalid sieve path %s, %s, %s", sieve_script_dir, sievename, userid); return 1; } /* Check if a default sieve filter alrady exists */ if(!stat(sieve_default,&statbuf)) { syslog(LOG_WARNING,"autocreate_sieve: Default sieve script already exists"); return 1; } /* Open the source script. if there is a problem with that exit */ in_stream = fopen(source_script, "r"); if(!in_stream) { syslog(LOG_WARNING,"autocreate_sieve: Unable to open sieve script %s. Check permissions",source_script); return 1; } /* * At this point we start the modifications of the filesystem */ /* Create the directory where the sieve scripts will reside */ r = cyrus_mkdir(sieve_bctmpname, 0755); if(r == -1) { /* If this fails we just leave */ fclose(in_stream); return 1; } /* * We open the file that will be used as the bc file. If this file exists, overwrite it * since something bad has happened. We open the file here so that this error checking is * done before we try to open the rest of the files to start copying etc. */ out_fd = open(sieve_bctmpname, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if(out_fd < 0) { if(errno == EEXIST) { syslog(LOG_WARNING,"autocreate_sieve: File %s already exists. Probaly left over. Ignoring",sieve_bctmpname); } else if (errno == EACCES) { syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_bctmpname); fclose(in_stream); return 1; } else { syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s: %m",sieve_bctmpname); fclose(in_stream); return 1; } } if(!do_compile && compiled_source_script && (in_fd = open(compiled_source_script, O_RDONLY)) != -1) { while((r = read(in_fd, buf, sizeof(buf))) > 0) { if((k=write(out_fd, buf,r)) < 0) { syslog(LOG_WARNING, "autocreate_sieve: Error writing to file %s: %m", sieve_bctmpname); close(out_fd); close(in_fd); fclose(in_stream); unlink(sieve_bctmpname); return 1; } } if(r == 0) { /* EOF */ xclose(out_fd); xclose(in_fd); } else if (r < 0) { syslog(LOG_WARNING, "autocreate_sieve: Error reading compiled script file %s: %m. Will try to compile it", compiled_source_script); xclose(in_fd); do_compile = 1; if(lseek(out_fd, 0, SEEK_SET)) { syslog(LOG_WARNING, "autocreate_sieve: Major IO problem (lseek: %m). Aborting"); xclose(out_fd); return 1; } } xclose(in_fd); } else { if(compiled_source_script) syslog(LOG_WARNING,"autocreate_sieve: Problem opening compiled script file: %s. Compiling it", compiled_source_script); do_compile = 1; } /* Because we failed to open a precompiled bc sieve script, we compile one */ if(do_compile) { if(is_script_parsable(in_stream,&err, &s) == TIMSIEVE_FAIL) { if(err && *err) { syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script %s.",err); free(err); } else syslog(LOG_WARNING,"autocreate_sieve: Error while parsing script"); unlink(sieve_bctmpname); fclose(in_stream); close(out_fd); return 1; } /* generate the bytecode */ if(sieve_generate_bytecode(&bc, s) == TIMSIEVE_FAIL) { syslog(LOG_WARNING,"autocreate_sieve: problem compiling sieve script"); /* removing the copied script and cleaning up memory */ unlink(sieve_bctmpname); sieve_script_free(&s); fclose(in_stream); close(out_fd); return 1; } if(sieve_emit_bytecode(out_fd, bc) == TIMSIEVE_FAIL) { syslog(LOG_WARNING,"autocreate_sieve: problem emiting sieve script"); /* removing the copied script and cleaning up memory */ unlink(sieve_bctmpname); sieve_free_bytecode(&bc); sieve_script_free(&s); fclose(in_stream); close(out_fd); return 1; } /* clean up the memory */ sieve_free_bytecode(&bc); sieve_script_free(&s); } xclose(out_fd); rewind(in_stream); /* Copy the initial script */ oldmask = umask(077); if((out_fp = fopen(sieve_tmpname, "w")) == NULL) { syslog(LOG_WARNING,"autocreate_sieve: Unable to open destination sieve script %s: %m", sieve_tmpname); unlink(sieve_bctmpname); umask(oldmask); fclose(in_stream); return 1; } umask(oldmask); while((r = fread(buf,sizeof(char), sizeof(buf), in_stream)) > 0) { if( fwrite(buf,sizeof(char), r, out_fp) != (unsigned)r) { syslog(LOG_WARNING,"autocreate_sieve: Problem writing to sieve script file %s: %m",sieve_tmpname); fclose(out_fp); unlink(sieve_tmpname); unlink(sieve_bctmpname); fclose(in_stream); return 1; } } if(feof(in_stream)) { fclose(out_fp); fclose(in_stream); } else { /* ferror */ fclose(out_fp); unlink(sieve_tmpname); unlink(sieve_bctmpname); fclose(in_stream); return 1; } /* Renaming the necessary stuff */ if(rename(sieve_tmpname, sieve_script_name)) { unlink(sieve_tmpname); unlink(sieve_bctmpname); return 1; } if(rename(sieve_bctmpname, sieve_bcscript_name)) { unlink(sieve_bctmpname); unlink(sieve_bcscript_name); return 1; } /* end now with the symlink */ if(symlink(sieve_bclink_name, sieve_default)) { if(errno != EEXIST) { syslog(LOG_WARNING, "autocreate_sieve: problem making the default link (symlink: %m)."); /* Lets delete the files */ unlink(sieve_script_name); unlink(sieve_bcscript_name); } } /* * If everything has succeeded AND we have compiled the script AND we have requested * to generate the global script so that it is not compiled each time then we create it. */ if(do_compile && config_getswitch(IMAPOPT_AUTOCREATE_SIEVE_SCRIPT_COMPILE)) { if(!compiled_source_script) { syslog(LOG_WARNING, "autocreate_sieve: To save a compiled sieve script, autocreate_sieve_compiledscript must have been defined in imapd.conf"); return 0; } if(snprintf(sieve_tmpname, MAX_FILENAME, "%s.NEW", compiled_source_script) >= MAX_FILENAME) return 0; /* * Copy everything from the newly created bc sieve sieve script. */ if((in_fd = open(sieve_bcscript_name, O_RDONLY))<0) { return 0; } if((out_fd = open(sieve_tmpname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) { if(errno == EEXIST) { /* Someone is already doing this so just bail out. */ syslog(LOG_WARNING, "autocreate_sieve: %s already exists. Some other instance processing it, or it is left over", sieve_tmpname); close(in_fd); return 0; } else if (errno == EACCES) { syslog(LOG_WARNING,"autocreate_sieve: No access to create file %s. Check permissions",sieve_tmpname); close(in_fd); return 0; } else { syslog(LOG_WARNING,"autocreate_sieve: Unable to create %s: %m",sieve_tmpname); close(in_fd); return 0; } } while((r = read(in_fd, buf, sizeof(buf))) > 0) { if((k = write(out_fd,buf,r)) < 0) { syslog(LOG_WARNING, "autocreate_sieve: Error writing to file: %s: %m", sieve_tmpname); close(out_fd); close(in_fd); unlink(sieve_tmpname); return 0; } } if(r == 0 ) { /*EOF */ xclose(out_fd); xclose(in_fd); } else if (r < 0) { syslog(LOG_WARNING, "autocreate_sieve: Error reading file: %s: %m", sieve_bcscript_name); xclose(out_fd); xclose(in_fd); unlink(sieve_tmpname); return 0; } /* Rename the temporary created sieve script to its final name. */ if(rename(sieve_tmpname, compiled_source_script)) { if(errno != EEXIST) { unlink(sieve_tmpname); unlink(compiled_source_script); } return 0; } syslog(LOG_NOTICE, "autocreate_sieve: Compiled sieve script was successfully saved in %s", compiled_source_script); } return 0; }