static gboolean cache_etag_file_start(liVRequest *vr, cache_etag_file *cfile) { cfile->tmpfilename = g_string_sized_new(cfile->filename->len + 7); g_string_append_len(cfile->tmpfilename, GSTR_LEN(cfile->filename)); g_string_append_len(cfile->tmpfilename, CONST_STR_LEN("-XXXXXX")); if (!mkdir_for_file(vr, cfile->tmpfilename->str)) { return FALSE; } errno = 0; /* posix doesn't define any errors */ if (-1 == (cfile->fd = mkstemp(cfile->tmpfilename->str))) { VR_ERROR(vr, "Couldn't create cache tempfile '%s': %s", cfile->tmpfilename->str, g_strerror(errno)); return FALSE; } #ifdef FD_CLOEXEC fcntl(cfile->fd, F_SETFD, FD_CLOEXEC); #endif return TRUE; }
int mkdir_for_file(const char *file, mode_t m) { char path[PATH_MAX], *eos; int rv, len = strlen(file); if(len == 0) { errno = ENOENT; return -1; } strlcpy(path, file, sizeof(path)); eos = path + len - 1; while(eos > path && *eos != '/') eos--; if(eos == path) { errno = ENOENT; return -1; } *eos = '\0'; rv = mkdir(path, m); if(rv == 0 || errno == EEXIST) return 0; if(errno == ENOENT) if(mkdir_for_file(path, m) != 0) return -1; rv = mkdir(path, m); if(rv < 0 && errno == EEXIST) rv = 0; return rv; }
static interim_journal_t * interim_journal_get(struct sockaddr *remote, const char *remote_cn_in, int storagenode_id, const char *fqdn_in) { void *vhash, *vij; mtev_hash_table *working_set; interim_journal_t *ij; struct timeval now; char jpath[PATH_MAX]; char remote_str[128]; const char *remote_cn = remote_cn_in ? remote_cn_in : "default"; const char *fqdn = fqdn_in ? fqdn_in : "default"; mtev_convert_sockaddr_to_buff(remote_str, sizeof(remote_str), remote); if(!*remote_str) strlcpy(remote_str, "default", sizeof(remote_str)); /* Lookup the working set */ if(!mtev_hash_retrieve(&working_sets, remote_cn, strlen(remote_cn), &vhash)) { working_set = calloc(1, sizeof(*working_set)); mtev_hash_store(&working_sets, strdup(remote_cn), strlen(remote_cn), working_set); } else working_set = vhash; /* Lookup the interim journal within the working set */ if(!mtev_hash_retrieve(working_set, fqdn, strlen(fqdn), &vij)) { ij = calloc(1, sizeof(*ij)); gettimeofday(&now, NULL); snprintf(jpath, sizeof(jpath), "%s/%s/%s/%d/%08x%08x.tmp", basejpath, remote_str, remote_cn, storagenode_id, (unsigned int)now.tv_sec, (unsigned int)now.tv_usec); ij->remote_str = strdup(remote_str); ij->remote_cn = strdup(remote_cn); ij->fqdn = fqdn_in ? strdup(fqdn_in) : NULL; ij->storagenode_id = storagenode_id; ij->filename = strdup(jpath); ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); if(ij->fd < 0 && errno == ENOENT) { if(mkdir_for_file(ij->filename, 0750)) { mtevL(noit_error, "Failed to create dir for '%s': %s\n", ij->filename, strerror(errno)); exit(-1); } ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); } if(ij->fd < 0 && errno == EEXIST) { /* This can only occur if we crash after before checkpointing */ unlink(ij->filename); ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); } if(ij->fd < 0) { mtevL(noit_error, "Failed to open interim journal '%s': %s\n", ij->filename, strerror(errno)); exit(-1); } mtev_hash_store(working_set, strdup(fqdn), strlen(fqdn), ij); } else ij = vij; return ij; }