+static asl_out_dst_data_t *
+_asl_out_dest_for_path(asl_out_module_t *m, const char *path)
+{
+ if (m == NULL) return NULL;
+ if (path == NULL) return NULL;
+
+ while (m != NULL)
+ {
+ asl_out_rule_t *r = m->ruleset;
+ while (r != NULL)
+ {
+ if ((r->action == ACTION_OUT_DEST) && (r->dst != NULL) && (r->dst->path != NULL) && (!strcmp(r->dst->path, path))) return r->dst;
+ r = r->next;
+ }
+
+ m = m->next;
+ }
+
+ return NULL;
+}
+
+/*
+ * Create a directory path.
+ *
+ * mlist provides owner, group, and access mode, which are required for "non-standard"
+ * directories. Directories for standard paths (/var/log or /Library/Logs) default
+ * to root/admin/0755 if there is no mlist rule for them.
+ */
+static int
+_asl_common_make_dir_path(asl_out_module_t *mlist, uint32_t flags, const char *path)
+{
+ int i;
+ char **path_parts;
+ asl_string_t *processed_path;
+ mode_t mode;
+
+ if (path == NULL) return 0;
+
+ path_parts = explode(path, "/");
+ if (path_parts == NULL) return 0;
+
+ processed_path = asl_string_new(ASL_ENCODE_NONE);
+
+ i = 0;
+ if (path[0] == '/') i = 1;
+
+ for (; path_parts[i] != NULL; i++)
+ {
+ struct stat sb;
+ int status;
+ mode_t mask;
+ asl_out_dst_data_t *dst;
+ char *tmp;
+
+ asl_string_append_char_no_encoding(processed_path, '/');
+ asl_string_append_no_encoding(processed_path, path_parts[i]);
+ tmp = asl_string_bytes(processed_path);
+
+ memset(&sb, 0, sizeof(struct stat));
+ status = lstat(tmp, &sb);
+ if ((status == 0) && S_ISLNK(sb.st_mode))
+ {
+ char real[MAXPATHLEN];
+ if (realpath(tmp, real) == NULL)
+ {
+ asl_string_release(processed_path);
+ free_string_list(path_parts);
+ return -1;
+ }
+
+ memset(&sb, 0, sizeof(struct stat));
+ status = stat(real, &sb);
+ }
+
+ if (status == 0)
+ {
+ if (!S_ISDIR(sb.st_mode))
+ {
+ /* path component is not a directory! */
+ asl_string_release(processed_path);
+ free_string_list(path_parts);
+ return -1;
+ }
+
+ /* exists and is a directory or a link to a directory */
+ continue;
+ }
+ else if (errno != ENOENT)
+ {
+ /* unexpected status from stat() */
+ asl_string_release(processed_path);
+ free_string_list(path_parts);
+ return -1;
+ }
+
+ dst = _asl_out_dest_for_path(mlist, tmp);
+ if ((dst == NULL) && (flags & MODULE_FLAG_NONSTD_DIR))
+ {
+ /* no rule to create a non-standard path component! */
+ asl_string_release(processed_path);
+ free_string_list(path_parts);
+ return -1;
+ }
+
+ mode = 0755;
+ if (dst != NULL)
+ {
+ mode = dst->mode;
+ if (mode == 010000) mode = 0755;
+ }
+
+ mask = umask(0);
+ status = mkdir(tmp, mode);
+ umask(mask);
+
+#if !TARGET_IPHONE_SIMULATOR
+ uid_t u = 0;
+ gid_t g = 80;
+
+ if (dst != NULL)
+ {
+ if (dst->nuid > 0) u = dst->uid[0];
+ if (dst->ngid > 0) g = dst->gid[0];
+ }
+
+ chown(tmp, u, g);
+#endif
+ }
+
+ asl_string_release(processed_path);
+ free_string_list(path_parts);
+
+ return 0;
+}
+