int mkdirhier(char *path, mode_t mask) { struct fattr *fa; size_t i, last, len; int error, finish, rv; finish = 0; last = 0; len = strlen(path); for (i = len - 1; i > 0; i--) { if (path[i] == '/') { path[i] = '\0'; if (access(path, F_OK) == 0) { path[i] = '/'; break; } if (errno != ENOENT) { path[i] = '/'; if (last == 0) return (-1); finish = 1; break; } last = i; } } if (last == 0) return (0); i = strlen(path); fa = fattr_new(FT_DIRECTORY, -1); fattr_mergedefault(fa); fattr_umask(fa, mask); while (i < len) { if (!finish) { rv = 0; error = fattr_makenode(fa, path); if (!error) rv = fattr_install(fa, path, NULL); if (error || rv == -1) finish = 1; } path[i] = '/'; i += strlen(path + i); } assert(i == len); if (finish) return (-1); return (0); }
/* * Open the status file. If scantime is not -1, the file is opened * for updating, otherwise, it is opened read-only. If the status file * couldn't be opened, NULL is returned and errmsg is set to the error * message. */ struct status * status_open(struct coll *coll, time_t scantime, char **errmsg) { struct status *st; struct stream *file; struct fattr *fa; char *destpath, *path; int error, rv; path = coll_statuspath(coll); file = stream_open_file(path, O_RDONLY); if (file == NULL) { if (errno != ENOENT) { xasprintf(errmsg, "Could not open \"%s\": %s\n", path, strerror(errno)); free(path); return (NULL); } st = status_fromnull(path); } else { st = status_fromrd(path, file); if (st == NULL) { xasprintf(errmsg, "Error in \"%s\": Bad header line", path); free(path); return (NULL); } } if (scantime != -1) { /* Open for writing too. */ xasprintf(&destpath, "%s/%s/%s/", coll->co_base, coll->co_colldir, coll->co_name); st->tempfile = tempname(destpath); if (mkdirhier(destpath, coll->co_umask) != 0) { xasprintf(errmsg, "Cannot create directories leading " "to \"%s\": %s", destpath, strerror(errno)); free(destpath); status_free(st); return (NULL); } free(destpath); st->wr = stream_open_file(st->tempfile, O_CREAT | O_TRUNC | O_WRONLY, 0644); if (st->wr == NULL) { xasprintf(errmsg, "Cannot create \"%s\": %s", st->tempfile, strerror(errno)); status_free(st); return (NULL); } fa = fattr_new(FT_FILE, -1); fattr_mergedefault(fa); fattr_umask(fa, coll->co_umask); rv = fattr_install(fa, st->tempfile, NULL); fattr_free(fa); if (rv == -1) { xasprintf(errmsg, "Cannot set attributes for \"%s\": %s", st->tempfile, strerror(errno)); status_free(st); return (NULL); } if (scantime != st->scantime) st->dirty = 1; error = proto_printf(st->wr, "F %d %t\n", STATUS_VERSION, scantime); if (error) { st->error = STATUS_ERR_WRITE; st->suberror = errno; *errmsg = status_errmsg(st); status_free(st); return (NULL); } } return (st); }