📄 tempfile.c
字号:
/* -*- c-file-style: "java"; indent-tabs-mode: nil -*- * * distcc -- A simple distributed compiler system * * Copyright (C) 2002, 2003, 2004 by Martin Pool <mbp@samba.org> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA */ /* "More computing sins are committed in the name of * efficiency (without necessarily achieving it) than * for any other single reason - including blind * stupidity." -- W.A. Wulf */#include "config.h"#include <sys/stat.h>#include <sys/types.h>#include <sys/time.h>#include <time.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <fcntl.h>#include <errno.h>#include "distcc.h"#include "trace.h"#include "util.h"#include "snprintf.h"#include "exitcode.h"/** * @file * * Routines for naming, generating and removing temporary files. * * Temporary files are stored under $TMPDIR or /tmp. * * From 2.10 on, our lock and state files are not stored in there. * * It would be nice if we could use a standard function, but I don't * think any of them are adequate: we need to control the extension * and know the filename. tmpfile() does not give back the filename. * tmpnam() is insecure. mkstemp() does not allow us to set the * extension. * * It sucks that there is no standard function. The implementation * below is inspired by the __gen_tempname() code in glibc; hopefully * it will be secure on all platforms. * * We need to touch the filename before running commands on it, * because we cannot be sure that the compiler will create it * securely. * * Even with all this, we are not necessarily secure in the presence * of a tmpreaper if the attacker can play timing tricks. However, * since we are not setuid and since there is no completely safe way * to write tmpreapers, this is left alone for now. * * If you're really paranoid, you should just use per-user TMPDIRs. * * @sa http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/avoid-race.html#TEMPORARY-FILES **/int dcc_get_tmp_top(const char **p_ret){ const char *d; d = getenv("TMPDIR"); if (!d || d[0] == '\0') { *p_ret = "/tmp"; return 0; } else { *p_ret = d; return 0; }}/** * Create the directory @p path. If it already exists as a directory * we succeed. **/int dcc_mkdir(const char *path){ if ((mkdir(path, 0777) == -1) && (errno != EEXIST)) { rs_log_error("mkdir %s failed: %s", path, strerror(errno)); return EXIT_IO_ERROR; } return 0;}/** * Return a static string holding DISTCC_DIR, or ~/.distcc. * The directory is created if it does not exist. **/int dcc_get_top_dir(char **path_ret){ char *env; static char *cached; int ret; if (cached) { *path_ret = cached; return 0; } if ((env = getenv("DISTCC_DIR"))) { if ((cached = strdup(env)) == NULL) { return EXIT_OUT_OF_MEMORY; } else { *path_ret = cached; return 0; } } if ((env = getenv("HOME")) == NULL) { rs_log_warning("HOME is not set; can't find distcc directory"); return EXIT_BAD_ARGUMENTS; } if (asprintf(path_ret, "%s/.distcc", env) == -1) { rs_log_error("asprintf failed"); return EXIT_OUT_OF_MEMORY; } ret = dcc_mkdir(*path_ret); if (ret == 0) cached = *path_ret; return ret;}/** * Return a subdirectory of the DISTCC_DIR of the given name, making * sure that the directory exists. **/static int dcc_get_subdir(const char *name, char **dir_ret){ int ret; char *topdir; if ((ret = dcc_get_top_dir(&topdir))) return ret; if (asprintf(dir_ret, "%s/%s", topdir, name) == -1) { rs_log_error("asprintf failed"); return EXIT_OUT_OF_MEMORY; } return dcc_mkdir(*dir_ret);}int dcc_get_lock_dir(char **dir_ret){ static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("lock", dir_ret); if (ret == 0) cached = *dir_ret; return ret; }}int dcc_get_state_dir(char **dir_ret){ static char *cached; int ret; if (cached) { *dir_ret = cached; return 0; } else { ret = dcc_get_subdir("state", dir_ret); if (ret == 0) cached = *dir_ret; return ret; }}/** * Create a file inside the temporary directory and register it for * later cleanup, and return its name. * * The file will be reopened later, possibly in a child. But we know * that it exists with appropriately tight permissions. **/int dcc_make_tmpnam(const char *prefix, const char *suffix, char **name_ret){ char *s = NULL; const char *tempdir; int ret; unsigned long random_bits; int fd; if ((ret = dcc_get_tmp_top(&tempdir))) return ret; if (access(tempdir, W_OK|X_OK) == -1) { rs_log_error("can't use TMPDIR \"%s\": %s", tempdir, strerror(errno)); return EXIT_IO_ERROR; } random_bits = (unsigned long) getpid() << 16;# if HAVE_GETTIMEOFDAY { struct timeval tv; gettimeofday(&tv, NULL); random_bits ^= tv.tv_usec << 16; random_bits ^= tv.tv_sec; }# else random_bits ^= time(NULL);# endif#if 0 random_bits = 0; /* FOR TESTING */#endif do { free(s); if (asprintf(&s, "%s/%s_%08lx%s", tempdir, prefix, random_bits & 0xffffffffUL, suffix) == -1) return EXIT_OUT_OF_MEMORY; /* Note that if the name already exists as a symlink, this * open call will fail. * * The permissions are tight because nobody but this process * and our children should do anything with it. */ fd = open(s, O_WRONLY | O_CREAT | O_EXCL, 0600); if (fd == -1) { /* try again */ rs_trace("failed to create %s: %s", s, strerror(errno)); random_bits += 7777; /* fairly prime */ continue; } if (close(fd) == -1) { /* huh? */ rs_log_warning("failed to close %s: %s", s, strerror(errno)); return EXIT_IO_ERROR; } break; } while (1); if ((ret = dcc_add_cleanup(s))) { free(s); return ret; } *name_ret = s; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -