Hello community, here is the log from the commit of package s3backer for openSUSE:Factory checked in at 2019-06-01 09:49:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/s3backer (Old) and /work/SRC/openSUSE:Factory/.s3backer.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "s3backer" Sat Jun 1 09:49:58 2019 rev:14 rq:706049 version:1.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/s3backer/s3backer.changes 2018-06-13 15:39:34.276161064 +0200 +++ /work/SRC/openSUSE:Factory/.s3backer.new.5148/s3backer.changes 2019-06-01 09:50:01.907313388 +0200 @@ -1,0 +2,9 @@ +Mon Apr 15 20:37:59 UTC 2019 - [email protected] + +- Update to release 1.5.1 + + Fixed a few places where fixed-sized buffers were too small (issue #108) + + Don't claim cache hit if partial write required reading the block (pr #103) + + Exit process with error code if s3backer store setup fails at startup + + Reset statistics if stats file is unlinked (issue #106) + +------------------------------------------------------------------- Old: ---- s3backer-1.5.0.tar.gz New: ---- s3backer-1.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ s3backer.spec ++++++ --- /var/tmp/diff_new_pack.KLtSq7/_old 2019-06-01 09:50:02.631313141 +0200 +++ /var/tmp/diff_new_pack.KLtSq7/_new 2019-06-01 09:50:02.639313139 +0200 @@ -1,7 +1,7 @@ # # spec file for package s3backer # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # Copyright 2008 Archie L. Cobbs. # # All modifications and additions to the file contributed by third parties @@ -18,10 +18,10 @@ Name: s3backer -Version: 1.5.0 +Version: 1.5.1 Release: 0 Summary: FUSE-based single file backing store via Amazon S3 -License: GPL-2.0+ +License: GPL-2.0-or-later Group: System/Filesystems Source: https://s3.amazonaws.com/archie-public/%{name}/%{name}-%{version}.tar.gz Url: https://github.com/archiecobbs/%{name} ++++++ s3backer-1.5.0.tar.gz -> s3backer-1.5.1.tar.gz ++++++ ++++ 2718 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/CHANGES new/s3backer-1.5.1/CHANGES --- old/s3backer-1.5.0/CHANGES 2018-06-09 22:00:34.000000000 +0200 +++ new/s3backer-1.5.1/CHANGES 2019-04-15 22:31:38.000000000 +0200 @@ -1,3 +1,10 @@ +Version 1.5.1 released April 15, 2019 + + - Fixed a few places where fixed-sized buffers were too small (issue #108) + - Don't claim cache hit if partial write required reading the block (pr #103) + - Exit process with error code if s3backer store setup fails at startup + - Reset statistics if stats file is unlinked (issue #106) + Version 1.5.0 released June 9, 2018 - Add support for recovering dirty blocks in the disk cache (issue #87) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/block_cache.c new/s3backer-1.5.1/block_cache.c --- old/s3backer-1.5.0/block_cache.c 2018-06-09 22:00:21.000000000 +0200 +++ new/s3backer-1.5.1/block_cache.c 2019-03-07 02:43:01.000000000 +0100 @@ -495,6 +495,16 @@ pthread_mutex_unlock(&priv->mutex); } +void +block_cache_clear_stats(struct s3backer_store *s3b) +{ + struct block_cache_private *const priv = s3b->data; + + pthread_mutex_lock(&priv->mutex); + memset(&priv->stats, 0, sizeof(priv->stats)); + pthread_mutex_unlock(&priv->mutex); +} + static int block_cache_list_blocks(struct s3backer_store *s3b, block_list_func_t *callback, void *arg) { @@ -773,6 +783,7 @@ { struct block_cache_conf *const config = priv->config; struct cache_entry *entry; + int partial_miss = 0; int r; /* Sanity check */ @@ -827,7 +838,8 @@ if ((r = block_cache_write_data(priv, entry, src, off, len)) != 0) (*config->log)(LOG_ERR, "error updating dirty block! %s", strerror(r)); entry->dirty = 1; - priv->stats.write_hits++; + if (!partial_miss) + priv->stats.write_hits++; break; default: assert(0); @@ -843,6 +855,8 @@ if (off != 0 || len != config->block_size) { if ((r = block_cache_do_read(priv, block_num, 0, 0, NULL, 0)) != 0) goto fail; + if (partial_miss++ == 0) + priv->stats.write_misses++; goto again; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/block_cache.h new/s3backer-1.5.1/block_cache.h --- old/s3backer-1.5.0/block_cache.h 2018-06-09 22:00:21.000000000 +0200 +++ new/s3backer-1.5.1/block_cache.h 2019-03-07 02:43:38.000000000 +0100 @@ -69,4 +69,5 @@ /* block_cache.c */ extern struct s3backer_store *block_cache_create(struct block_cache_conf *config, struct s3backer_store *inner); extern void block_cache_get_stats(struct s3backer_store *s3b, struct block_cache_stats *stats); +extern void block_cache_clear_stats(struct s3backer_store *s3b); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/config.h.in new/s3backer-1.5.1/config.h.in --- old/s3backer-1.5.0/config.h.in 2018-06-09 22:03:37.000000000 +0200 +++ new/s3backer-1.5.1/config.h.in 2019-04-15 22:33:00.000000000 +0200 @@ -148,5 +148,8 @@ /* MacOS functions */ #undef _DARWIN_C_SOURCE +/* Default functions */ +#undef _DEFAULT_SOURCE + /* GNU functions */ #undef _GNU_SOURCE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/configure.ac new/s3backer-1.5.1/configure.ac --- old/s3backer-1.5.0/configure.ac 2018-06-09 22:00:34.000000000 +0200 +++ new/s3backer-1.5.1/configure.ac 2019-04-12 01:49:02.000000000 +0200 @@ -32,7 +32,7 @@ # this exception statement from all source files in the program, then # also delete it here. -AC_INIT([s3backer FUSE filesystem backed by Amazon S3], [1.5.0], [https://github.com/archiecobbs/s3backer], [s3backer]) +AC_INIT([s3backer FUSE filesystem backed by Amazon S3], [1.5.1], [https://github.com/archiecobbs/s3backer], [s3backer]) AC_CONFIG_AUX_DIR(scripts) AM_INIT_AUTOMAKE(foreign) dnl AM_MAINTAINER_MODE @@ -43,9 +43,10 @@ [CFLAGS="-g -O3 -pipe -Wall -Waggregate-return -Wcast-align -Wchar-subscripts -Wcomment -Wformat -Wimplicit -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wno-long-long -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wswitch -Wtrigraphs -Wuninitialized -Wunused -Wwrite-strings -Wshadow -Wstrict-prototypes -Wcast-qual $CFLAGS"] AC_SUBST(CFLAGS) -# Compile flags for Linux +# Compile flags for Linux. See https://stackoverflow.com/a/29201732 AC_DEFINE(_GNU_SOURCE, 1, GNU functions) AC_DEFINE(_BSD_SOURCE, 1, BSD functions) +AC_DEFINE(_DEFAULT_SOURCE, 1, Default functions) # Compile flags for Mac OS AC_DEFINE(_DARWIN_C_SOURCE, 1, MacOS functions) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/ec_protect.c new/s3backer-1.5.1/ec_protect.c --- old/s3backer-1.5.0/ec_protect.c 2018-05-31 00:09:31.000000000 +0200 +++ new/s3backer-1.5.1/ec_protect.c 2019-03-07 02:43:31.000000000 +0100 @@ -306,6 +306,16 @@ pthread_mutex_unlock(&priv->mutex); } +void +ec_protect_clear_stats(struct s3backer_store *s3b) +{ + struct ec_protect_private *const priv = s3b->data; + + pthread_mutex_lock(&priv->mutex); + memset(&priv->stats, 0, sizeof(priv->stats)); + pthread_mutex_unlock(&priv->mutex); +} + static int ec_protect_list_blocks(struct s3backer_store *s3b, block_list_func_t *callback, void *arg) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/ec_protect.h new/s3backer-1.5.1/ec_protect.h --- old/s3backer-1.5.0/ec_protect.h 2017-04-01 18:05:52.000000000 +0200 +++ new/s3backer-1.5.1/ec_protect.h 2019-03-07 02:41:46.000000000 +0100 @@ -55,4 +55,5 @@ /* ec_protect.c */ extern struct s3backer_store *ec_protect_create(struct ec_protect_conf *config, struct s3backer_store *inner); extern void ec_protect_get_stats(struct s3backer_store *s3b, struct ec_protect_stats *stats); +extern void ec_protect_clear_stats(struct s3backer_store *s3b); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/fuse_ops.c new/s3backer-1.5.1/fuse_ops.c --- old/s3backer-1.5.0/fuse_ops.c 2018-05-31 00:09:31.000000000 +0200 +++ new/s3backer-1.5.1/fuse_ops.c 2019-04-13 19:49:52.000000000 +0200 @@ -89,6 +89,7 @@ static int fuse_op_truncate(const char *path, off_t size); static int fuse_op_flush(const char *path, struct fuse_file_info *fi); static int fuse_op_fsync(const char *path, int isdatasync, struct fuse_file_info *fi); +static int fuse_op_unlink(const char *path); #if FUSE_FALLOCATE static int fuse_op_fallocate(const char *path, int mode, off_t offset, off_t len, struct fuse_file_info *fi); #endif @@ -121,6 +122,7 @@ .flush = fuse_op_flush, .fsync = fuse_op_fsync, .release = fuse_op_release, + .unlink = fuse_op_unlink, #if FUSE_FALLOCATE .fallocate = fuse_op_fallocate, #endif @@ -128,18 +130,33 @@ /* Configuration and underlying s3backer_store */ static struct fuse_ops_conf *config; +static struct fuse_ops_private *the_priv; /**************************************************************************** * PUBLIC FUNCTION DEFINITIONS * ****************************************************************************/ const struct fuse_operations * -fuse_ops_create(struct fuse_ops_conf *config0) +fuse_ops_create(struct fuse_ops_conf *config0, struct s3backer_store *s3b) { - if (config != NULL) { - (*config0->log)(LOG_ERR, "s3backer_get_fuse_ops(): duplicate invocation"); + /* Sanity check */ + assert(config0 != NULL); + assert(s3b != NULL); + + /* Prevent duplicate invocation */ + if (config != NULL || the_priv != NULL) { + (*config0->log)(LOG_ERR, "fuse_ops_create(): duplicate invocation"); + return NULL; + } + + /* Create private structure */ + if ((the_priv = calloc(1, sizeof(*the_priv))) == NULL) { + (*config->log)(LOG_ERR, "fuse_ops_create(): %s", strerror(errno)); return NULL; } + the_priv->s3b = s3b; + + /* Now we're ready */ config = config0; return &s3backer_fuse_ops; } @@ -152,28 +169,16 @@ fuse_op_init(struct fuse_conn_info *conn) { struct s3b_config *const s3bconf = config->s3bconf; - struct fuse_ops_private *priv; + struct fuse_ops_private *const priv = the_priv; - /* Create private structure */ - if ((priv = calloc(1, sizeof(*priv))) == NULL) { - (*config->log)(LOG_ERR, "fuse_op_init(): %s", strerror(errno)); - exit(1); - } + assert(priv != NULL); + assert(priv->s3b != NULL); priv->block_bits = ffs(config->block_size) - 1; priv->start_time = time(NULL); priv->file_atime = priv->start_time; priv->file_mtime = priv->start_time; priv->stats_atime = priv->start_time; priv->file_size = config->num_blocks * config->block_size; - - /* Create backing store */ - if ((priv->s3b = s3backer_create_store(s3bconf)) == NULL) { - (*config->log)(LOG_ERR, "fuse_op_init(): can't create s3backer_store: %s", strerror(errno)); - free(priv); - return NULL; - } - - /* Done */ (*config->log)(LOG_INFO, "mounting %s", s3bconf->mount); return priv; } @@ -540,6 +545,22 @@ return 0; } +static int +fuse_op_unlink(const char *path) +{ + /* Handle stats file */ + if (*path == '/' && strcmp(path + 1, config->stats_filename) == 0) { + if (config->clear_stats == NULL) + return -EOPNOTSUPP; + (*config->clear_stats)(); + return 0; + } + + /* Not supported */ + return -EOPNOTSUPP; +} + + #if FUSE_FALLOCATE static int fuse_op_fallocate(const char *path, int mode, off_t offset, off_t len, struct fuse_file_info *fi) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/fuse_ops.h new/s3backer-1.5.1/fuse_ops.h --- old/s3backer-1.5.0/fuse_ops.h 2017-04-01 18:05:52.000000000 +0200 +++ new/s3backer-1.5.1/fuse_ops.h 2019-03-07 02:45:39.000000000 +0100 @@ -36,15 +36,18 @@ /* Forward decl's */ struct s3b_config; +struct s3backer_store; /* Function types */ typedef void printer_t(void *prarg, const char *fmt, ...) __attribute__ ((__format__ (__printf__, 2, 3))); typedef void print_stats_t(void *prarg, printer_t *printer); +typedef void clear_stats_t(void); /* Configuration info structure for fuse_ops */ struct fuse_ops_conf { struct s3b_config *s3bconf; print_stats_t *print_stats; + clear_stats_t *clear_stats; int read_only; int direct_io; const char *filename; @@ -58,5 +61,5 @@ }; /* fuse_ops.c */ -const struct fuse_operations *fuse_ops_create(struct fuse_ops_conf *config); +const struct fuse_operations *fuse_ops_create(struct fuse_ops_conf *config, struct s3backer_store *s3b); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/gitrev.c new/s3backer-1.5.1/gitrev.c --- old/s3backer-1.5.0/gitrev.c 2018-06-09 22:03:40.000000000 +0200 +++ new/s3backer-1.5.1/gitrev.c 2019-04-15 22:33:06.000000000 +0200 @@ -1 +1 @@ -const char *const s3backer_version = "1.5.0"; +const char *const s3backer_version = "1.5.1"; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/http_io.c new/s3backer-1.5.1/http_io.c --- old/s3backer-1.5.0/http_io.c 2018-06-03 03:09:15.000000000 +0200 +++ new/s3backer-1.5.1/http_io.c 2019-04-12 01:51:37.000000000 +0200 @@ -258,8 +258,8 @@ static size_t http_io_curl_reader(const void *ptr, size_t size, size_t nmemb, void *stream); static size_t http_io_curl_writer(void *ptr, size_t size, size_t nmemb, void *stream); static size_t http_io_curl_header(void *ptr, size_t size, size_t nmemb, void *stream); -static struct curl_slist *http_io_add_header(struct curl_slist *headers, const char *fmt, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); +static struct curl_slist *http_io_add_header(struct http_io_private *priv, struct curl_slist *headers, const char *fmt, ...) + __attribute__ ((__format__ (__printf__, 3, 4))); static void http_io_add_date(struct http_io_private *priv, struct http_io *const io, time_t now); static CURL *http_io_acquire_curl(struct http_io_private *priv, struct http_io *io); static void http_io_release_curl(struct http_io_private *priv, CURL **curlp, int may_cache); @@ -341,6 +341,10 @@ CRYPTO_set_locking_callback(http_io_openssl_locker); CRYPTO_set_id_callback(http_io_openssl_ider); + /* Avoid GCC unused-function warnings */ + (void)http_io_openssl_locker; + (void)http_io_openssl_ider; + /* Initialize encryption */ if (config->encryption != NULL) { char saltbuf[strlen(config->bucket) + 1 + strlen(config->prefix) + 1]; @@ -501,6 +505,16 @@ pthread_mutex_unlock(&priv->mutex); } +void +http_io_clear_stats(struct s3backer_store *s3b) +{ + struct http_io_private *const priv = s3b->data; + + pthread_mutex_lock(&priv->mutex); + memset(&priv->stats, 0, sizeof(priv->stats)); + pthread_mutex_unlock(&priv->mutex); +} + static int http_io_list_blocks(struct s3backer_store *s3b, block_list_func_t *callback, void *arg) { @@ -873,28 +887,28 @@ MD5_Final(md5, &ctx); /* Add Content-Type header */ - io.headers = http_io_add_header(io.headers, "%s: %s", CTYPE_HEADER, MOUNT_TOKEN_FILE_MIME_TYPE); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", CTYPE_HEADER, MOUNT_TOKEN_FILE_MIME_TYPE); /* Add Content-MD5 header */ http_io_base64_encode(md5buf, sizeof(md5buf), md5, MD5_DIGEST_LENGTH); - io.headers = http_io_add_header(io.headers, "%s: %s", MD5_HEADER, md5buf); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", MD5_HEADER, md5buf); /* Add Mount-Token header */ - io.headers = http_io_add_header(io.headers, "%s: %08x", MOUNT_TOKEN_HEADER, (int)new_value); + io.headers = http_io_add_header(priv, io.headers, "%s: %08x", MOUNT_TOKEN_HEADER, (int)new_value); /* Add ACL header */ - io.headers = http_io_add_header(io.headers, "%s: %s", ACL_HEADER, config->accessType); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", ACL_HEADER, config->accessType); } /* Add Server Side Encryption value (if needed) */ if (config->sse != NULL) - io.headers = http_io_add_header(io.headers, "%s: %s", SSE_HEADER, config->sse); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", SSE_HEADER, config->sse); /* Add storage class header (if needed) */ storage_class = config->storage_class != NULL ? config->storage_class : config->rrs ? STORAGE_CLASS_REDUCED_REDUNDANCY : NULL; if (storage_class != NULL) - io.headers = http_io_add_header(io.headers, "%s: %s", STORAGE_CLASS_HEADER, storage_class); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", STORAGE_CLASS_HEADER, storage_class); /* Add Authorization header */ if ((r = http_io_add_auth(priv, &io, now, io.src, io.buf_size)) != 0) @@ -914,7 +928,7 @@ update_iam_credentials(struct http_io_private *const priv) { struct http_io_conf *const config = priv->config; - char urlbuf[sizeof(EC2_IAM_META_DATA_URLBASE) + 128]; + char *urlbuf; struct http_io io; char buf[2048] = { '\0' }; char *access_id = NULL; @@ -924,7 +938,10 @@ int r; /* Build URL */ - snprintf(urlbuf, sizeof(urlbuf), "%s%s", EC2_IAM_META_DATA_URLBASE, config->ec2iam_role); + if (asprintf(&urlbuf, "%s%s", EC2_IAM_META_DATA_URLBASE, config->ec2iam_role) == -1) { + (*config->log)(LOG_ERR, "%s: asprintf() failed: %s", "update_iam_credentials", strerror(ENOMEM)); + return ENOMEM; + } /* Initialize I/O info */ memset(&io, 0, sizeof(io)); @@ -937,8 +954,10 @@ (*config->log)(LOG_INFO, "acquiring EC2 IAM credentials from %s", io.url); if ((r = http_io_perform_io(priv, &io, http_io_iamcreds_prepper)) != 0) { (*config->log)(LOG_ERR, "failed to acquire EC2 IAM credentials from %s: %s", io.url, strerror(r)); + free(urlbuf); return r; } + free(urlbuf); /* Determine how many bytes we read */ buflen = io.buf_size - io.bufs.rdremain; @@ -1116,7 +1135,7 @@ io.expect_304 = 1; } http_io_prhex(md5buf, expect_md5, MD5_DIGEST_LENGTH); - io.headers = http_io_add_header(io.headers, "%s: \"%s\"", header, md5buf); + io.headers = http_io_add_header(priv, io.headers, "%s: \"%s\"", header, md5buf); } /* Set Accept-Encoding header */ @@ -1125,7 +1144,7 @@ snprintf(accepted_encodings + strlen(accepted_encodings), sizeof(accepted_encodings) - strlen(accepted_encodings), ", %s-%s", CONTENT_ENCODING_ENCRYPT, config->encryption); } - io.headers = http_io_add_header(io.headers, "%s: %s", ACCEPT_ENCODING_HEADER, accepted_encodings); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", ACCEPT_ENCODING_HEADER, accepted_encodings); /* Add Authorization header */ if ((r = http_io_add_auth(priv, &io, now, NULL, 0)) != 0) @@ -1495,7 +1514,7 @@ snprintf(ebuf + strlen(ebuf), sizeof(ebuf) - strlen(ebuf), "%s%s-%s", compressed ? ", " : "", CONTENT_ENCODING_ENCRYPT, config->encryption); } - io.headers = http_io_add_header(io.headers, "%s", ebuf); + io.headers = http_io_add_header(priv, io.headers, "%s", ebuf); } /* Compute MD5 checksum */ @@ -1518,36 +1537,36 @@ if (src != NULL) { /* Add Content-Type header */ - io.headers = http_io_add_header(io.headers, "%s: %s", CTYPE_HEADER, CONTENT_TYPE); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", CTYPE_HEADER, CONTENT_TYPE); /* Add Content-MD5 header */ http_io_base64_encode(md5buf, sizeof(md5buf), md5, MD5_DIGEST_LENGTH); - io.headers = http_io_add_header(io.headers, "%s: %s", MD5_HEADER, md5buf); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", MD5_HEADER, md5buf); } /* Add ACL header (PUT only) */ if (src != NULL) - io.headers = http_io_add_header(io.headers, "%s: %s", ACL_HEADER, config->accessType); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", ACL_HEADER, config->accessType); /* Add file size meta-data to zero'th block */ if (src != NULL && block_num == 0) { - io.headers = http_io_add_header(io.headers, "%s: %u", BLOCK_SIZE_HEADER, config->block_size); - io.headers = http_io_add_header(io.headers, "%s: %ju", + io.headers = http_io_add_header(priv, io.headers, "%s: %u", BLOCK_SIZE_HEADER, config->block_size); + io.headers = http_io_add_header(priv, io.headers, "%s: %ju", FILE_SIZE_HEADER, (uintmax_t)(config->block_size * config->num_blocks)); } /* Add signature header (if encrypting) */ if (src != NULL && config->encryption != NULL) - io.headers = http_io_add_header(io.headers, "%s: \"%s\"", HMAC_HEADER, hmacbuf); + io.headers = http_io_add_header(priv, io.headers, "%s: \"%s\"", HMAC_HEADER, hmacbuf); /* Add Server Side Encryption header (if needed) */ if (config->sse != NULL) - io.headers = http_io_add_header(io.headers, "%s: %s", SSE_HEADER, config->sse); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", SSE_HEADER, config->sse); /* Add storage class header (if needed) */ storage_class = config->storage_class != NULL ? config->storage_class : config->rrs ? STORAGE_CLASS_REDUCED_REDUNDANCY : NULL; if (storage_class != NULL) - io.headers = http_io_add_header(io.headers, "%s: %s", STORAGE_CLASS_HEADER, storage_class); + io.headers = http_io_add_header(priv, io.headers, "%s: %s", STORAGE_CLASS_HEADER, storage_class); /* Add Authorization header */ if ((r = http_io_add_auth(priv, &io, now, io.src, io.buf_size)) != 0) @@ -1949,7 +1968,7 @@ #endif /* Add auth header */ - io->headers = http_io_add_header(io->headers, "%s: AWS %s:%s", AUTH_HEADER, access_id, authbuf); + io->headers = http_io_add_header(priv, io->headers, "%s: AWS %s:%s", AUTH_HEADER, access_id, authbuf); /* Done */ r = 0; @@ -1998,7 +2017,7 @@ char datebuf[DATE_BUF_SIZE]; char access_id[128]; char access_key[128]; - char iam_token[1024]; + char *iam_token = NULL; struct tm tm; char *p; int r; @@ -2011,13 +2030,19 @@ pthread_mutex_lock(&priv->mutex); snprintf(access_id, sizeof(access_id), "%s", config->accessId); snprintf(access_key, sizeof(access_key), "%s%s", ACCESS_KEY_PREFIX, config->accessKey); - snprintf(iam_token, sizeof(iam_token), "%s", config->iam_token != NULL ? config->iam_token : ""); + if (config->iam_token != NULL && (iam_token = strdup(config->iam_token)) == NULL) { + r = errno; + pthread_mutex_unlock(&priv->mutex); + (*config->log)(LOG_ERR, "%s: strdup: %s", "http_io_add_auth4", strerror(r)); + goto fail; + } pthread_mutex_unlock(&priv->mutex); /* Extract host, URI path, and query parameters from URL */ if ((p = strchr(io->url, ':')) == NULL || *++p != '/' || *++p != '/' || (host = p + 1) == NULL || (uripath = strchr(host, '/')) == NULL) { r = EINVAL; + free(iam_token); goto fail; } host_len = uripath - host; @@ -2042,12 +2067,14 @@ EVP_DigestFinal_ex(hash_ctx, payload_hash, &payload_hash_len); http_io_prhex(payload_hash_buf, payload_hash, payload_hash_len); - io->headers = http_io_add_header(io->headers, "%s: %s", CONTENT_SHA256_HEADER, payload_hash_buf); + io->headers = http_io_add_header(priv, io->headers, "%s: %s", CONTENT_SHA256_HEADER, payload_hash_buf); /****** Add IAM security token header (if any) ******/ - if (*iam_token != '\0') - io->headers = http_io_add_header(io->headers, "%s: %s", SECURITY_TOKEN_HEADER, iam_token); + if (iam_token != NULL && *iam_token != '\0') { + io->headers = http_io_add_header(priv, io->headers, "%s: %s", SECURITY_TOKEN_HEADER, iam_token); + free(iam_token); + } /****** Create Hashed Canonical Request ******/ @@ -2244,7 +2271,7 @@ /****** Add Authorization Header ******/ - io->headers = http_io_add_header(io->headers, "%s: %s Credential=%s/%.8s/%s/%s/%s, SignedHeaders=%s, Signature=%s", + io->headers = http_io_add_header(priv, io->headers, "%s: %s Credential=%s/%.8s/%s/%s/%s, SignedHeaders=%s, Signature=%s", AUTH_HEADER, SIGNATURE_ALGORITHM, access_id, datebuf, config->region, S3_SERVICE_NAME, SIGNATURE_TERMINATOR, header_names, hmac_buf); @@ -2345,22 +2372,26 @@ if (strcmp(config->authVersion, AUTH_VERSION_AWS2) == 0) { strftime(buf, sizeof(buf), HTTP_DATE_BUF_FMT, gmtime_r(&now, &tm)); - io->headers = http_io_add_header(io->headers, "%s: %s", HTTP_DATE_HEADER, buf); + io->headers = http_io_add_header(priv, io->headers, "%s: %s", HTTP_DATE_HEADER, buf); } else { strftime(buf, sizeof(buf), AWS_DATE_BUF_FMT, gmtime_r(&now, &tm)); - io->headers = http_io_add_header(io->headers, "%s: %s", AWS_DATE_HEADER, buf); + io->headers = http_io_add_header(priv, io->headers, "%s: %s", AWS_DATE_HEADER, buf); } } static struct curl_slist * -http_io_add_header(struct curl_slist *headers, const char *fmt, ...) +http_io_add_header(struct http_io_private *priv, struct curl_slist *headers, const char *fmt, ...) { - char buf[1024]; + char *buf; va_list args; va_start(args, fmt); - vsnprintf(buf, sizeof(buf), fmt, args); - headers = curl_slist_append(headers, buf); + if (vasprintf(&buf, fmt, args) == -1) + (*priv->config->log)(LOG_ERR, "%s: vasprintf() failed: %s", "http_io_add_header", strerror(ENOMEM)); + else { + headers = curl_slist_append(headers, buf); + free(buf); + } va_end(args); return headers; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/http_io.h new/s3backer-1.5.1/http_io.h --- old/s3backer-1.5.0/http_io.h 2017-06-30 19:12:31.000000000 +0200 +++ new/s3backer-1.5.1/http_io.h 2019-03-07 02:40:58.000000000 +0100 @@ -138,5 +138,6 @@ /* http_io.c */ extern struct s3backer_store *http_io_create(struct http_io_conf *config); extern void http_io_get_stats(struct s3backer_store *s3b, struct http_io_stats *stats); +extern void http_io_clear_stats(struct s3backer_store *s3b); extern int http_io_parse_block(struct http_io_conf *config, const char *name, s3b_block_t *block_num); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/main.c new/s3backer-1.5.1/main.c --- old/s3backer-1.5.0/main.c 2017-04-01 18:05:52.000000000 +0200 +++ new/s3backer-1.5.1/main.c 2019-02-28 16:08:40.000000000 +0100 @@ -47,6 +47,7 @@ main(int argc, char **argv) { const struct fuse_operations *fuse_ops; + struct s3backer_store *s3b; struct s3b_config *config; /* Get configuration */ @@ -67,8 +68,17 @@ return 0; } - /* Get FUSE operation hooks */ - fuse_ops = fuse_ops_create(&config->fuse_ops); + /* Create backing store */ + if ((s3b = s3backer_create_store(config)) == NULL) { + (*config->log)(LOG_ERR, "error creating s3backer_store: %s", strerror(errno)); + return 1; + } + + /* Setup FUSE operation hooks */ + if ((fuse_ops = fuse_ops_create(&config->fuse_ops, s3b)) == NULL) { + (*s3b->destroy)(s3b); + return 1; + } /* Start */ (*config->log)(LOG_INFO, "s3backer process %lu for %s started", (u_long)getpid(), config->mount); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/s3b_config.c new/s3backer-1.5.1/s3b_config.c --- old/s3backer-1.5.0/s3b_config.c 2018-06-09 22:00:21.000000000 +0200 +++ new/s3backer-1.5.1/s3b_config.c 2019-03-07 02:45:22.000000000 +0100 @@ -106,6 +106,7 @@ ****************************************************************************/ static print_stats_t s3b_config_print_stats; +static clear_stats_t s3b_config_clear_stats; static int parse_size_string(const char *s, uintmax_t *valp); static void unparse_size_string(char *buf, size_t bmax, uintmax_t value); @@ -582,6 +583,7 @@ /* Set up fuse_ops callbacks */ config.fuse_ops.print_stats = s3b_config_print_stats; + config.fuse_ops.clear_stats = s3b_config_clear_stats; config.fuse_ops.s3bconf = &config; /* Debug */ @@ -593,7 +595,7 @@ } /* - * Create the s3backer_store used at runtime. This method is invoked by fuse_op_init(). + * Create the s3backer_store used at runtime. */ struct s3backer_store * s3backer_create_store(struct s3b_config *conf) @@ -778,6 +780,22 @@ (*printer)(prarg, "%-28s %u\n", "out_of_memory_errors", total_oom); } +static void +s3b_config_clear_stats(void) +{ + /* Clear HTTP stats */ + if (http_io_store != NULL) + http_io_clear_stats(http_io_store); + + /* Clear EC protection stats */ + if (ec_protect_store != NULL) + ec_protect_clear_stats(ec_protect_store); + + /* Clear block cache stats */ + if (block_cache_store != NULL) + block_cache_clear_stats(block_cache_store); +} + static int parse_size_string(const char *s, uintmax_t *valp) { @@ -1229,7 +1247,7 @@ } if (config.file_size_str != NULL) { if (parse_size_string(config.file_size_str, &value) == -1 || value == 0) { - warnx("invalid file size `%s'", config.block_size_str); + warnx("invalid file size `%s'", config.file_size_str); return -1; } config.file_size = value; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/s3backer.1 new/s3backer-1.5.1/s3backer.1 --- old/s3backer-1.5.0/s3backer.1 2018-06-09 22:00:34.000000000 +0200 +++ new/s3backer-1.5.1/s3backer.1 2019-03-16 23:37:21.000000000 +0100 @@ -269,9 +269,10 @@ .Ss Statistics File .Nm populates the filesystem with a human-readable statistics file. -See +Use .Fl \-statsFilename -below. +to change the name of this file (default `stats'). +The statistics can be reset to zero by attempting to remove the file. .Ss Logging In normal operation .Nm diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/s3backer.spec new/s3backer-1.5.1/s3backer.spec --- old/s3backer-1.5.0/s3backer.spec 2018-06-09 22:03:40.000000000 +0200 +++ new/s3backer-1.5.1/s3backer.spec 2019-04-15 22:33:06.000000000 +0200 @@ -29,7 +29,7 @@ # Name: s3backer -Version: 1.5.0 +Version: 1.5.1 Release: 1 License: GNU General Public License, Version 2 Summary: FUSE-based single file backing store via Amazon S3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/scripts/compile new/s3backer-1.5.1/scripts/compile --- old/s3backer-1.5.0/scripts/compile 1970-01-01 01:00:00.000000000 +0100 +++ new/s3backer-1.5.1/scripts/compile 2019-04-15 22:33:01.000000000 +0200 @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2016-01-11.22; # UTC + +# Copyright (C) 1999-2017 Free Software Foundation, Inc. +# Written by Tom Tromey <[email protected]>. +# +# 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, 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, see <http://www.gnu.org/licenses/>. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to <[email protected]> or send patches to +# <[email protected]>. + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to <[email protected]>. +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/s3backer-1.5.0/scripts/missing new/s3backer-1.5.1/scripts/missing --- old/s3backer-1.5.0/scripts/missing 2018-06-09 22:03:37.000000000 +0200 +++ new/s3backer-1.5.1/scripts/missing 2019-04-15 22:33:01.000000000 +0200 @@ -1,9 +1,9 @@ #! /bin/sh # Common wrapper for a few potentially missing GNU programs. -scriptversion=2012-06-26.16; # UTC +scriptversion=2016-01-11.22; # UTC -# Copyright (C) 1996-2013 Free Software Foundation, Inc. +# Copyright (C) 1996-2017 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard <[email protected]>, 1996. # This program is free software; you can redistribute it and/or modify @@ -160,7 +160,7 @@ ;; autom4te*) echo "You might have modified some maintainer files that require" - echo "the 'automa4te' program to be rebuilt." + echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) @@ -210,6 +210,6 @@ # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" +# time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End:
