diff --git a/WHATS_NEW b/WHATS_NEW index 42fb45d4f..e26a2d76e 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.28 - ================================ + Detect stream write failure reliably; new fn: lvm_fclose; use dm_fclose Fix clvmd if compiled with gulm support. (2.02.26) Trivial fix to lvdisplay man page. Add vg_lock_and_read() external library function. diff --git a/lib/config/config.c b/lib/config/config.c index f15f46dc4..3c2d49b22 100644 --- a/lib/config/config.c +++ b/lib/config/config.c @@ -20,6 +20,7 @@ #include "str_list.h" #include "toolcontext.h" #include "lvm-string.h" +#include "lvm-file.h" #include #include @@ -520,8 +521,8 @@ int write_config_file(struct config_tree *cft, const char *file, argv++; } - if (outline.fp && fclose(outline.fp)) { - log_sys_error("fclose", file); + if (outline.fp && lvm_fclose(outline.fp, file)) { + stack; r = 0; } diff --git a/lib/filters/filter-persistent.c b/lib/filters/filter-persistent.c index f07b246f8..26f8db632 100644 --- a/lib/filters/filter-persistent.c +++ b/lib/filters/filter-persistent.c @@ -239,10 +239,8 @@ int persistent_filter_dump(struct dev_filter *f) /* _write_array(pf, fp, "invalid_devices", PF_BAD_DEVICE); */ fprintf(fp, "}\n"); - if (fclose(fp)) { - log_sys_error("fclose", tmp_file); - goto out; - } + if (lvm_fclose(fp, tmp_file)) + goto_out; if (rename(tmp_file, pf->file)) log_error("%s: rename to %s failed: %s", tmp_file, pf->file, diff --git a/lib/format_text/archive.c b/lib/format_text/archive.c index c6af857b1..047cf80b3 100644 --- a/lib/format_text/archive.c +++ b/lib/format_text/archive.c @@ -261,11 +261,8 @@ int archive_vg(struct volume_group *vg, return 0; } - if (fclose(fp)) { - log_sys_error("fclose", temp_file); - /* Leave file behind as evidence of failure */ - return 0; - } + if (lvm_fclose(fp, temp_file)) + return_0; /* Leave file behind as evidence of failure */ /* * Now we want to rename this file to _index.vg. diff --git a/lib/format_text/format-text.c b/lib/format_text/format-text.c index e8bf6f6fe..05ee7986c 100644 --- a/lib/format_text/format-text.c +++ b/lib/format_text/format-text.c @@ -892,10 +892,8 @@ static int _vg_write_file(struct format_instance *fid, struct volume_group *vg, return 0; } - if (fclose(fp)) { - log_sys_error("fclose", tc->path_edit); - return 0; - } + if (lvm_fclose(fp, tc->path_edit)) + return_0; if (rename(temp_file, tc->path_edit)) { log_debug("Renaming %s to %s", temp_file, tc->path_edit); diff --git a/lib/log/log.c b/lib/log/log.c index a67abe675..9566ea129 100644 --- a/lib/log/log.c +++ b/lib/log/log.c @@ -17,6 +17,7 @@ #include "device.h" #include "memlock.h" #include "lvm-string.h" +#include "lvm-file.h" #include "defaults.h" #include @@ -121,8 +122,14 @@ void fin_log(void) } if (_log_to_file) { - if (fclose(_log_file)) - fprintf(stderr, "fclose() on log file failed: %s", strerror(errno)); + if (dm_fclose(_log_file)) { + if (errno) + fprintf(stderr, "failed to write log file: %s\n", + strerror(errno)); + else + fprintf(stderr, "failed to write log file\n"); + + } _log_to_file = 0; } } diff --git a/lib/misc/lvm-file.c b/lib/misc/lvm-file.c index d2c5f3d5f..339f32d72 100644 --- a/lib/misc/lvm-file.c +++ b/lib/misc/lvm-file.c @@ -321,3 +321,13 @@ void fcntl_unlock_file(int lockfd) strerror(errno)); } +int lvm_fclose(FILE *fp, const char *filename) +{ + if (!dm_fclose(fp)) + return 0; + if (errno == 0) + log_error("%s: write error", filename); + else + log_sys_error("write error", filename); + return EOF; +} diff --git a/lib/misc/lvm-file.h b/lib/misc/lvm-file.h index f5da9a9ac..a0ff41d35 100644 --- a/lib/misc/lvm-file.h +++ b/lib/misc/lvm-file.h @@ -56,4 +56,13 @@ void fcntl_unlock_file(int lockfd); ((buf1).st_ino == (buf2).st_ino && \ (buf1).st_dev == (buf2).st_dev) +/* + * Close the specified stream, taking care to detect and diagnose any write + * error. If there is an error, use the supplied file name in a diagnostic + * that is reported via log_error or log_sys_error, as appropriate. + * Use this function to close a stream when you've written data to it via + * unchecked fprintf, fputc, etc. calls. Return 0 on success, EOF on failure. + */ +int lvm_fclose(FILE *fp, const char *filename); + #endif