diff --git a/common.h b/common.h index bad4ef70..4c2584e9 100644 --- a/common.h +++ b/common.h @@ -119,7 +119,7 @@ typedef struct { int daemonise_store_pid; // don't try to save a PID file char *piddir; char *computed_piddir; // the actual pid directory to create, if any - int logOutputLevel; // log output level + int logOutputLevel; // log output level int statistics_requested, use_negotiated_latencies; enum playback_mode_type playback_mode; char *cmd_start, *cmd_stop, *cmd_set_volume; diff --git a/mdns_dns_sd.c b/mdns_dns_sd.c index b4b7e4ac..5785d103 100644 --- a/mdns_dns_sd.c +++ b/mdns_dns_sd.c @@ -24,8 +24,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "mdns.h" #include "common.h" +#include "mdns.h" #include #include #include diff --git a/mdns_external.c b/mdns_external.c index fcd3a323..b8698b8c 100644 --- a/mdns_external.c +++ b/mdns_external.c @@ -24,8 +24,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "mdns.h" #include "common.h" +#include "mdns.h" #include #include #include diff --git a/shairport.c b/shairport.c index a2645f7a..130700fe 100644 --- a/shairport.c +++ b/shairport.c @@ -114,6 +114,54 @@ static void sig_connect_audio_output(int foo, siginfo_t *bar, void *baz) { set_requested_connection_state_to_output(1); } +// The following two functions are adapted slightly and with thanks from Jonathan Leffler's sample +// code at +// https://stackoverflow.com/questions/675039/how-can-i-create-directory-tree-in-c-linux + +int do_mkdir(const char *path, mode_t mode) { + struct stat st; + int status = 0; + + if (stat(path, &st) != 0) { + /* Directory does not exist. EEXIST for race condition */ + if (mkdir(path, mode) != 0 && errno != EEXIST) + status = -1; + } else if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + status = -1; + } + + return (status); +} + +// mkpath - ensure all directories in path exist +// Algorithm takes the pessimistic view and works top-down to ensure +// each directory in path exists, rather than optimistically creating +// the last element and working backwards. + +int mkpath(const char *path, mode_t mode) { + char *pp; + char *sp; + int status; + char *copypath = strdup(path); + + status = 0; + pp = copypath; + while (status == 0 && (sp = strchr(pp, '/')) != 0) { + if (sp != pp) { + /* Neither root nor double slash in path */ + *sp = '\0'; + status = do_mkdir(copypath, mode); + *sp = '/'; + } + pp = sp + 1; + } + if (status == 0) + status = do_mkdir(path, mode); + free(copypath); + return (status); +} + char *get_version_string() { char *version_string = malloc(200); if (version_string) { @@ -893,8 +941,8 @@ int parse_options(int argc, char **argv) { free(i2); free(i3); free(vs); - - // now, check and calculate the pid directory + +// now, check and calculate the pid directory #ifdef USE_CUSTOM_PID_DIR char *use_this_pid_dir = PIDDIR; #else @@ -954,7 +1002,7 @@ void shairport_startup_complete(void) { } const char *pid_file_proc(void) { - + char fn[8192]; snprintf(fn, sizeof(fn), "%s/%s.pid", config.computed_piddir, daemon_pid_file_ident ? daemon_pid_file_ident : "unknown"); @@ -1180,10 +1228,23 @@ int main(int argc, char **argv) { return 255; } - if (ret != 0) - daemon_log(ret != 0 ? LOG_ERR : LOG_INFO, "Daemon returned %i as return value.", ret); + switch (ret) { + case 0: + break; + case 1: + daemon_log(LOG_ERR, + "daemon failed to launch: could not close open file descriptors after forking."); + break; + case 2: + daemon_log(LOG_ERR, "daemon failed to launch: could not create PID file."); + break; + case 3: + daemon_log(LOG_ERR, "daemon failed to launch: could not create or access PID directory."); + break; + default: + daemon_log(LOG_ERR, "daemon failed to launch, error %i.", ret); + } return ret; - } else { /* The daemon */ /* Close FDs */ @@ -1198,7 +1259,13 @@ int main(int argc, char **argv) { /* Create the PID file if required */ if (config.daemonise_store_pid) { /* Create the PID directory if required -- we don't really care about the result */ - mkdir(config.computed_piddir, 0700); + printf("PID directory is \"%s\".", config.computed_piddir); + int result = mkpath(config.computed_piddir, 0700); + if ((result != 0) && (result != -EEXIST)) { + // error creating or accessing the PID file directory + daemon_retval_send(3); + goto finish; + } if (daemon_pid_file_create() < 0) { daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); daemon_retval_send(2);