diff --git a/apps/app_dial.c b/apps/app_dial.c index 7ecf8eef13d635119cf93676ce65ac7a36e75918..035604e6786acd6584330c79d81dc96280affa89 100644 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -1146,13 +1146,13 @@ static int setup_privacy_args(struct privacy_args *pa, /* make sure the priv-callerintros dir actually exists */ snprintf(pa->privintro, sizeof(pa->privintro), "%s/sounds/priv-callerintros", ast_config_AST_DATA_DIR); - if (mkdir(pa->privintro, 0755) && errno != EEXIST) { - ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(errno)); + if ((res = ast_mkdir(pa->privintro, 0755))) { + ast_log(LOG_WARNING, "privacy: can't create directory priv-callerintros: %s\n", strerror(res)); return -1; } - snprintf(pa->privintro,sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid); - if (ast_fileexists(pa->privintro,NULL,NULL ) > 0 && strncmp(pa->privcid,"NOCALLERID",10) != 0) { + snprintf(pa->privintro, sizeof(pa->privintro), "priv-callerintros/%s", pa->privcid); + if (ast_fileexists(pa->privintro, NULL, NULL ) > 0 && strncmp(pa->privcid, "NOCALLERID", 10) != 0) { /* the DELUX version of this code would allow this caller the option to hear and retape their previously recorded intro. */ diff --git a/apps/app_dictate.c b/apps/app_dictate.c index c501b3f7840043df2194f26d64dc9ab09c3efd71..61252433d43cab83fac63e812e06e5225024c05b 100644 --- a/apps/app_dictate.c +++ b/apps/app_dictate.c @@ -139,7 +139,7 @@ static int dictate_exec(struct ast_channel *chan, void *data) ast_copy_string(filein, filename, sizeof(filein)); filename = ""; } - mkdir(base, 0755); + ast_mkdir(base, 0755); len = strlen(base) + strlen(filein) + 2; if (!path || len > maxlen) { path = alloca(len); diff --git a/apps/app_minivm.c b/apps/app_minivm.c index 682520b1c769777b8ee09784ee713161f9115f74..73ef61b289b07dec9bb4dc23ed3f47f7d0d88104 100644 --- a/apps/app_minivm.c +++ b/apps/app_minivm.c @@ -1159,28 +1159,11 @@ static int check_dirpath(char *dest, int len, char *domain, char *username, char */ static int create_dirpath(char *dest, int len, char *domain, char *username, char *folder) { - mode_t mode = VOICEMAIL_DIR_MODE; - - if(!ast_strlen_zero(domain)) { - make_dir(dest, len, domain, "", ""); - if(mkdir(dest, mode) && errno != EEXIST) { - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno)); - return -1; - } - } - if(!ast_strlen_zero(username)) { - make_dir(dest, len, domain, username, ""); - if(mkdir(dest, mode) && errno != EEXIST) { - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno)); - return -1; - } - } - if(!ast_strlen_zero(folder)) { - make_dir(dest, len, domain, username, folder); - if(mkdir(dest, mode) && errno != EEXIST) { - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno)); - return -1; - } + int res; + make_dir(dest, len, domain, username, folder); + if ((res = ast_mkdir(dest, 0777))) { + ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res)); + return -1; } ast_debug(2, "Creating directory for %s@%s folder %s : %s\n", username, domain, folder, dest); return 0; diff --git a/apps/app_sms.c b/apps/app_sms.c index f1022bb2676ca01f500007cb44f52ae579e066ff..d29ab6985ade54f4b04d1d392cd0f83ca3ebf47b 100644 --- a/apps/app_sms.c +++ b/apps/app_sms.c @@ -916,10 +916,8 @@ static void sms_writefile(sms_t * h) char buf[30]; FILE *o; - ast_copy_string(fn, spool_dir, sizeof (fn)); - mkdir(fn, 0777); /* ensure it exists */ - snprintf(fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx"); - mkdir(fn, 0777); /* ensure it exists */ + snprintf(fn, sizeof(fn), "%s/%s", spool_dir, h->smsc ? h->rx ? "morx" : "mttx" : h->rx ? "mtrx" : "motx"); + ast_mkdir(fn, 0777); /* ensure it exists */ ast_copy_string(fn2, fn, sizeof (fn2)); snprintf(fn2 + strlen (fn2), sizeof (fn2) - strlen (fn2), "/%s.%s-%d", h->queue, isodate(h->scts, buf, sizeof(buf)), seq++); snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/.%s", fn2 + strlen (fn) + 1); @@ -1339,11 +1337,9 @@ static void sms_nextoutgoing (sms_t * h) char more = 0; *h->da = *h->oa = '\0'; /* clear destinations */ - ast_copy_string (fn, spool_dir, sizeof (fn)); - mkdir(fn, 0777); /* ensure it exists */ h->rx = 0; /* outgoing message */ - snprintf (fn + strlen (fn), sizeof (fn) - strlen (fn), "/%s", h->smsc ? "mttx" : "motx"); - mkdir (fn, 0777); /* ensure it exists */ + snprintf(fn, sizeof(fn), "%s/%s", spool_dir, h->smsc ? "mttx" : "motx"); + ast_mkdir(fn, 0777); /* ensure it exists */ d = opendir (fn); if (d) { struct dirent *f = readdirqueue (d, h->queue); diff --git a/apps/app_test.c b/apps/app_test.c index a41403a18d93620edc4e9bc9bbb47c248b5c0c54..8bf7b9e8c801eb0ce2b02a04b0c708d1a7233cbd 100644 --- a/apps/app_test.c +++ b/apps/app_test.c @@ -177,7 +177,7 @@ static int testclient_exec(struct ast_channel *chan, void *data) if ((res >=0) && (!ast_strlen_zero(testid))) { /* Make the directory to hold the test results in case it's not there */ snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR); - mkdir(fn, 0777); + ast_mkdir(fn, 0777); snprintf(fn, sizeof(fn), "%s/testresults/%s-client.txt", ast_config_AST_LOG_DIR, testid); if ((f = fopen(fn, "w+"))) { setlinebuf(f); @@ -338,7 +338,7 @@ static int testserver_exec(struct ast_channel *chan, void *data) /* Got a Test ID! Whoo hoo! */ /* Make the directory to hold the test results in case it's not there */ snprintf(fn, sizeof(fn), "%s/testresults", ast_config_AST_LOG_DIR); - mkdir(fn, 0777); + ast_mkdir(fn, 0777); snprintf(fn, sizeof(fn), "%s/testresults/%s-server.txt", ast_config_AST_LOG_DIR, testid); if ((f = fopen(fn, "w+"))) { setlinebuf(f); diff --git a/apps/app_voicemail.c b/apps/app_voicemail.c index b68337c93fc177dbe445353e4f56857826a3d221..e5572dd58a7d093620e4a29a5e576ba9b26429e8 100644 --- a/apps/app_voicemail.c +++ b/apps/app_voicemail.c @@ -939,8 +939,9 @@ static int make_dir(char *dest, int len, const char *context, const char *ext, c #ifdef IMAP_STORAGE static int make_gsm_file(char *dest, char *imapuser, char *dir, int num) { - if (mkdir(dir, 01777) && (errno != EEXIST)) { - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno)); + int res; + if ((res = ast_mkdir(dir, 01777))) { + ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dir, strerror(res)); return sprintf(dest, "%s/msg%04d", dir, num); } /* return sprintf(dest, "%s/s/msg%04d", dir, imapuser, num); */ @@ -983,27 +984,12 @@ static int make_file(char *dest, int len, char *dir, int num) static int create_dirpath(char *dest, int len, const char *context, const char *ext, const char *folder) { mode_t mode = VOICEMAIL_DIR_MODE; + int res; - if (!ast_strlen_zero(context)) { - make_dir(dest, len, context, "", ""); - if (mkdir(dest, mode) && errno != EEXIST) { - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno)); - return -1; - } - } - if (!ast_strlen_zero(ext)) { - make_dir(dest, len, context, ext, ""); - if (mkdir(dest, mode) && errno != EEXIST) { - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno)); - return -1; - } - } - if (!ast_strlen_zero(folder)) { - make_dir(dest, len, context, ext, folder); - if (mkdir(dest, mode) && errno != EEXIST) { - ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dest, strerror(errno)); - return -1; - } + make_dir(dest, len, context, ext, folder); + if ((res = ast_mkdir(dest, mode))) { + ast_log(LOG_WARNING, "ast_mkdir '%s' failed: %s\n", dest, strerror(res)); + return -1; } return 0; } diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index 779db5ea06fa476428fc7b46d9cd661bc80bca99..76f90c7b0403e255a3ce40211f20545d90439b12 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -593,6 +593,16 @@ int _ast_vasprintf(char **ret, const char *file, int lineno, const char *func, c */ void ast_enable_packet_fragmentation(int sock); +/*! + \brief Recursively create directory path + \param path The directory path to create + \param mode The permissions with which to try to create the directory + \return 0 on success or an error code otherwise + + Creates a directory path, creating parent directories as needed. + */ +int ast_mkdir(const char *path, int mode); + #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0])) #include "asterisk/strings.h" diff --git a/main/logger.c b/main/logger.c index c64b634f4f850ec97825aba957f1a7b791dc7f4f..f02a18e5070851fd28427d8c0a859d06d4d15199 100644 --- a/main/logger.c +++ b/main/logger.c @@ -417,7 +417,7 @@ int reload_logger(int rotate) queue_rotate = 0; qlog = NULL; - mkdir(ast_config_AST_LOG_DIR, 0755); + ast_mkdir(ast_config_AST_LOG_DIR, 0777); AST_LIST_TRAVERSE(&logchannels, f, list) { if (f->disabled) { @@ -796,14 +796,13 @@ int init_logger(void) /* register the logger cli commands */ ast_cli_register_multiple(cli_logger, sizeof(cli_logger) / sizeof(struct ast_cli_entry)); - mkdir(ast_config_AST_LOG_DIR, 0755); + ast_mkdir(ast_config_AST_LOG_DIR, 0777); /* create log channels */ init_logger_chain(); /* create the eventlog */ if (logfiles.event_log) { - mkdir(ast_config_AST_LOG_DIR, 0755); snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, EVENTLOG); eventlog = fopen(tmp, "a"); if (eventlog) { diff --git a/main/utils.c b/main/utils.c index 7570ca608d265165dcd70f608d11c733645df3fe..65139356dc5aeb1d78d0cd3bd819fc78a5872ee5 100644 --- a/main/utils.c +++ b/main/utils.c @@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include <errno.h> #include <stdarg.h> #include <stdio.h> +#include <sys/stat.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -1058,3 +1059,39 @@ void ast_enable_packet_fragmentation(int sock) ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n"); #endif /* HAVE_IP_MTU_DISCOVER */ } + +int ast_mkdir(const char *path, int mode) +{ + char *ptr; + int len = strlen(path), count = 0, x, piececount = 0; + char *tmp = ast_strdupa(path); + char **pieces; + char *fullpath = alloca(len + 1); + int res = 0; + + for (ptr = tmp; *ptr; ptr++) { + if (*ptr == '/') + count++; + } + + /* Count the components to the directory path */ + pieces = alloca(count * sizeof(*pieces)); + for (ptr = tmp; *ptr; ptr++) { + if (*ptr == '/') { + *ptr = '\0'; + pieces[piececount++] = ptr + 1; + } + } + + *fullpath = '\0'; + for (x = 0; x < piececount; x++) { + /* This looks funky, but the buffer is always ideally-sized, so it's fine. */ + strcat(fullpath, "/"); + strcat(fullpath, pieces[x]); + res = mkdir(fullpath, mode); + if (res && errno != EEXIST) + return errno; + } + return 0; +} + diff --git a/pbx/pbx_spool.c b/pbx/pbx_spool.c index aaefef56dd16118723d848348af624cd7bc5dbbe..2888efaeb4b937112cb8ed645f8067e58374ebf9 100644 --- a/pbx/pbx_spool.c +++ b/pbx/pbx_spool.c @@ -294,7 +294,7 @@ static int remove_from_queue(struct outgoing *o, const char *status) unlink(o->fn); return 0; } - if (mkdir(qdonedir, 0700) && (errno != EEXIST)) { + if (ast_mkdir(qdonedir, 0777)) { ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir); unlink(o->fn); return -1; @@ -485,7 +485,7 @@ static int load_module(void) pthread_t thread; int ret; snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing"); - if (mkdir(qdir, 0700) && (errno != EEXIST)) { + if (ast_mkdir(qdir, 0777)) { ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir); return 0; } diff --git a/res/res_monitor.c b/res/res_monitor.c index a01d953a31f217f2167d2439d2264e62c9fd9cbb..9adf31e8cf0021d610234e558d9e38cf9fe185b3 100644 --- a/res/res_monitor.c +++ b/res/res_monitor.c @@ -128,7 +128,6 @@ int ast_monitor_start( struct ast_channel *chan, const char *format_spec, const char *fname_base, int need_lock) { int res = 0; - char tmp[256]; LOCK_IF_NEEDED(chan, need_lock); @@ -137,12 +136,7 @@ int ast_monitor_start( struct ast_channel *chan, const char *format_spec, char *channel_name, *p; /* Create monitoring directory if needed */ - if (mkdir(ast_config_AST_MONITOR_DIR, 0770) < 0) { - if (errno != EEXIST) { - ast_log(LOG_WARNING, "Unable to create audio monitor directory: %s\n", - strerror(errno)); - } - } + ast_mkdir(ast_config_AST_MONITOR_DIR, 0777); if (!(monitor = ast_calloc(1, sizeof(*monitor)))) { UNLOCK_IF_NEEDED(chan, need_lock); @@ -154,10 +148,8 @@ int ast_monitor_start( struct ast_channel *chan, const char *format_spec, int directory = strchr(fname_base, '/') ? 1 : 0; /* try creating the directory just in case it doesn't exist */ if (directory) { - char *name = ast_strdup(fname_base); - snprintf(tmp, sizeof(tmp), "mkdir -p \"%s\"",dirname(name)); - ast_free(name); - ast_safe_system(tmp); + char *name = ast_strdupa(fname_base); + ast_mkdir(dirname(name), 0777); } snprintf(monitor->read_filename, FILENAME_MAX, "%s/%s-in", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base); @@ -354,7 +346,6 @@ static int unpause_monitor_exec(struct ast_channel *chan, void *data) /* Change monitoring filename of a channel */ int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, int need_lock) { - char tmp[256]; if (ast_strlen_zero(fname_base)) { ast_log(LOG_WARNING, "Cannot change monitor filename of channel %s to null\n", chan->name); return -1; @@ -366,10 +357,8 @@ int ast_monitor_change_fname(struct ast_channel *chan, const char *fname_base, i int directory = strchr(fname_base, '/') ? 1 : 0; /* try creating the directory just in case it doesn't exist */ if (directory) { - char *name = ast_strdup(fname_base); - snprintf(tmp, sizeof(tmp), "mkdir -p %s",dirname(name)); - ast_free(name); - ast_safe_system(tmp); + char *name = ast_strdupa(fname_base); + ast_mkdir(dirname(name), 0777); } snprintf(chan->monitor->filename_base, FILENAME_MAX, "%s/%s", directory ? "" : ast_config_AST_MONITOR_DIR, fname_base);