summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2015-01-12 14:06:14 -0500
committerNick Mathewson <nickm@torproject.org>2015-01-12 14:06:14 -0500
commit2edfdc02a29e73a01f360f257d8dfe916a7a5b45 (patch)
treedccbc5984ff04448ef264d9bcdb404e5f0a85b46 /src/common
parentcacea9102a2431ce8e7e431629a91a43331ac9f9 (diff)
parentf8ffb57bc4430ff9bbd7560eecdda4284b2799ba (diff)
downloadtor-2edfdc02a29e73a01f360f257d8dfe916a7a5b45.tar.gz
tor-2edfdc02a29e73a01f360f257d8dfe916a7a5b45.zip
Merge remote-tracking branch 'teor/bug13111-empty-key-files-fn-empty'
Diffstat (limited to 'src/common')
-rw-r--r--src/common/compat.c1
-rw-r--r--src/common/util.c32
-rw-r--r--src/common/util.h2
3 files changed, 26 insertions, 9 deletions
diff --git a/src/common/compat.c b/src/common/compat.c
index 11e2545709..6d36321193 100644
--- a/src/common/compat.c
+++ b/src/common/compat.c
@@ -823,6 +823,7 @@ replace_file(const char *from, const char *to)
case FN_NOENT:
break;
case FN_FILE:
+ case FN_EMPTY:
if (unlink(to)) return -1;
break;
case FN_ERROR:
diff --git a/src/common/util.c b/src/common/util.c
index edd0ae895f..f7baab0791 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -2018,15 +2018,24 @@ clean_name_for_stat(char *name)
#endif
}
-/** Return FN_ERROR if filename can't be read, FN_NOENT if it doesn't
- * exist, FN_FILE if it is a regular file, or FN_DIR if it's a
- * directory. On FN_ERROR, sets errno. */
+/** Return:
+ * FN_ERROR if filename can't be read, is NULL, or is zero-length,
+ * FN_NOENT if it doesn't exist,
+ * FN_FILE if it is a non-empty regular file, or a FIFO on unix-like systems,
+ * FN_EMPTY for zero-byte regular files,
+ * FN_DIR if it's a directory, and
+ * FN_ERROR for any other file type.
+ * On FN_ERROR and FN_NOENT, sets errno. (errno is not set when FN_ERROR
+ * is returned due to an unhandled file type.) */
file_status_t
file_status(const char *fname)
{
struct stat st;
char *f;
int r;
+ if (!fname || strlen(fname) == 0) {
+ return FN_ERROR;
+ }
f = tor_strdup(fname);
clean_name_for_stat(f);
log_debug(LD_FS, "stat()ing %s", f);
@@ -2038,16 +2047,23 @@ file_status(const char *fname)
}
return FN_ERROR;
}
- if (st.st_mode & S_IFDIR)
+ if (st.st_mode & S_IFDIR) {
return FN_DIR;
- else if (st.st_mode & S_IFREG)
- return FN_FILE;
+ } else if (st.st_mode & S_IFREG) {
+ if (st.st_size > 0) {
+ return FN_FILE;
+ } else if (st.st_size == 0) {
+ return FN_EMPTY;
+ } else {
+ return FN_ERROR;
+ }
#ifndef _WIN32
- else if (st.st_mode & S_IFIFO)
+ } else if (st.st_mode & S_IFIFO) {
return FN_FILE;
#endif
- else
+ } else {
return FN_ERROR;
+ }
}
/** Check whether <b>dirname</b> exists and is private. If yes return 0. If
diff --git a/src/common/util.h b/src/common/util.h
index ee40949b61..1b8fc74db5 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -342,7 +342,7 @@ enum stream_status get_string_from_pipe(FILE *stream, char *buf, size_t count);
/** Return values from file_status(); see that function's documentation
* for details. */
-typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR } file_status_t;
+typedef enum { FN_ERROR, FN_NOENT, FN_FILE, FN_DIR, FN_EMPTY } file_status_t;
file_status_t file_status(const char *filename);
/** Possible behaviors for check_private_dir() on encountering a nonexistent