From 4604d03d985731fb0a42e62c0e5b0b626f4d6c64 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Fri, 4 Mar 2005 08:52:50 +0000 Subject: [PATCH] retaining old file if contents are the same --- libasn1compiler/asn1c_C.c | 5 +- libasn1compiler/asn1c_compat.c | 40 ++++++++++++---- libasn1compiler/asn1c_compat.h | 6 ++- libasn1compiler/asn1c_save.c | 85 ++++++++++++++++++++++++++++++---- libasn1compiler/asn1compiler.h | 2 +- 5 files changed, 115 insertions(+), 23 deletions(-) diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c index 5cd9e055..e35f534f 100644 --- a/libasn1compiler/asn1c_C.c +++ b/libasn1compiler/asn1c_C.c @@ -7,6 +7,7 @@ #include "asn1c_constraint.h" #include "asn1c_out.h" #include "asn1c_misc.h" +#include "asn1c_compat.h" #include /* Stuff exported by libasn1fix */ typedef struct tag2el_s { @@ -1703,9 +1704,9 @@ emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_ int using_type_name = 0; char *p; - OUT("/* %s defined in %s at line %d */\n", + OUT("/* %s defined in %s near line %d */\n", MKID_nc(expr->Identifier), - arg->mod->source_file_name, expr->_lineno); + a1c_basename(arg->mod->source_file_name), expr->_lineno); if(HIDE_INNER_DEFS) OUT("static /* Use -fall-defs-global to expose */\n"); OUT("asn_TYPE_descriptor_t asn_DEF_%s", MKID_nc(expr->Identifier)); diff --git a/libasn1compiler/asn1c_compat.c b/libasn1compiler/asn1c_compat.c index ebc6d3f0..2a80251a 100644 --- a/libasn1compiler/asn1c_compat.c +++ b/libasn1compiler/asn1c_compat.c @@ -14,7 +14,7 @@ #endif FILE * -asn1c_open_file(const char *name, const char *ext) { +asn1c_open_file(const char *name, const char *ext, char **opt_tmpname) { int created = 1; #ifndef WIN32 struct stat sb; @@ -22,22 +22,35 @@ asn1c_open_file(const char *name, const char *ext) { char *fname; size_t len; FILE *fp; + int ret; int fd; /* * Compute filenames. */ - len = strlen(name) + strlen(ext) + 1; + len = strlen(name) + strlen(ext) + sizeof(".XXXXXX"); fname = alloca(len); - snprintf(fname, len, "%s%s", name, ext); + ret = snprintf(fname, len, "%s%s%s", name, ext, + opt_tmpname ? ".XXXXXX" : ""); + assert(ret > 0 && ret < len); - /* - * Create files. - */ - fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE); - if(fd == -1 && errno == EEXIST) { - fd = open(fname, O_WRONLY, DEFFILEMODE); - created = 0; + if(opt_tmpname) { + /* + * Create temporary file. + */ + fd = mkstemp(fname); +#ifndef WIN32 + (void)fchmod(fd, DEFFILEMODE); +#endif + } else { + /* + * Create specified file, or open the old one. + */ + fd = open(fname, O_CREAT | O_EXCL | O_WRONLY, DEFFILEMODE); + if(fd == -1 && errno == EEXIST) { + fd = open(fname, O_WRONLY, DEFFILEMODE); + created = 0; + } } if(fd == -1) { perror(fname); @@ -68,6 +81,13 @@ asn1c_open_file(const char *name, const char *ext) { if(created) unlink(fname); close(fd); } + + /* Return the temporary file name */ + if(opt_tmpname) { + *opt_tmpname = strdup(fname); + assert(*opt_tmpname); + } + return fp; } diff --git a/libasn1compiler/asn1c_compat.h b/libasn1compiler/asn1c_compat.h index 44ac438c..8aa38654 100644 --- a/libasn1compiler/asn1c_compat.h +++ b/libasn1compiler/asn1c_compat.h @@ -3,8 +3,12 @@ /* * Open the arbitrary file by its base name and extension. + * If opt_tmpname is given, a temporary file will be created and + * its name returned in (*opt_tmpname). + * The (*opt_tmpname) should then be subsequently freed by free(3). */ -FILE *asn1c_open_file(const char *base_part, const char *extension); +FILE *asn1c_open_file(const char *base_part, const char *extension, + char **opt_tmpname); /* * Obtain base name and directory name of a path. diff --git a/libasn1compiler/asn1c_save.c b/libasn1compiler/asn1c_save.c index 1abf2427..2d0410f5 100644 --- a/libasn1compiler/asn1c_save.c +++ b/libasn1compiler/asn1c_save.c @@ -10,6 +10,7 @@ static int asn1c_dump_streams(arg_t *arg, asn1c_fdeps_t *); static int asn1c_print_streams(arg_t *arg); static int asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *); static int asn1c_copy_over(arg_t *arg, char *path); +static int identical_files(const char *fname1, const char *fname2); int asn1c_save_compiled_output(arg_t *arg, const char *datadir) { @@ -41,7 +42,7 @@ asn1c_save_compiled_output(arg_t *arg, const char *datadir) { return 0; /* Finished */ } - mkf = asn1c_open_file("Makefile.am", ".sample"); + mkf = asn1c_open_file("Makefile.am", ".sample", 0); if(mkf == NULL) { perror("Makefile.am.sample"); return -1; @@ -174,7 +175,11 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) { compiler_streams_t *cs = expr->data; out_chunk_t *ot; FILE *fp_c, *fp_h; + char *tmpname_c, *tmpname_h; + char *name_buf; char *header_id; + const char *c_retained = ""; + const char *h_retained = ""; if(cs == NULL) { fprintf(stderr, "Cannot compile %s at line %d\n", @@ -182,11 +187,11 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) { return -1; } - fp_c = asn1c_open_file(expr->Identifier, ".c"); - fp_h = asn1c_open_file(expr->Identifier, ".h"); + fp_c = asn1c_open_file(expr->Identifier, ".c", &tmpname_c); + fp_h = asn1c_open_file(expr->Identifier, ".h", &tmpname_h); if(fp_c == NULL || fp_h == NULL) { - if(fp_c) fclose(fp_c); /* lacks unlink() */ - if(fp_h) fclose(fp_h); /* lacks unlink() */ + if(fp_c) { unlink(tmpname_c); free(tmpname_c); fclose(fp_c); } + if(fp_h) { unlink(tmpname_h); free(tmpname_h); fclose(fp_h); } return -1; } @@ -250,11 +255,70 @@ asn1c_save_streams(arg_t *arg, asn1c_fdeps_t *deps) { fclose(fp_c); fclose(fp_h); - fprintf(stderr, "Compiled %s.c\n", expr->Identifier); - fprintf(stderr, "Compiled %s.h\n", expr->Identifier); + + name_buf = alloca(strlen(expr->Identifier) + 3); + + sprintf(name_buf, "%s.c", expr->Identifier); + if(identical_files(name_buf, tmpname_c)) { + c_retained = " (contents unchanged)"; + unlink(tmpname_c); + } else { + if(rename(tmpname_c, name_buf)) { + unlink(tmpname_c); + perror(tmpname_c); + return -1; + } + } + + sprintf(name_buf, "%s.h", expr->Identifier); + if(identical_files(name_buf, tmpname_h)) { + h_retained = " (contents unchanged)"; + unlink(tmpname_h); + } else { + if(rename(tmpname_h, name_buf)) { + unlink(tmpname_h); + perror(tmpname_h); + return -1; + } + } + + free(tmpname_c); + free(tmpname_h); + + fprintf(stderr, "Compiled %s.c%s\n", + expr->Identifier, c_retained); + fprintf(stderr, "Compiled %s.h%s\n", + expr->Identifier, h_retained); return 0; } +static int +identical_files(const char *fname1, const char *fname2) { + char buf[2][8192]; + FILE *fp1, *fp2; + size_t olen, nlen; + int retval = 1; /* Files are identical */ + + fp1 = fopen(fname1, "r"); + if(!fp1) { return 0; } + fp2 = fopen(fname2, "r"); + if(!fp2) { fclose(fp1); return 0; } + + while((olen = fread(buf[0], 1, sizeof(buf[0]), fp1))) { + nlen = fread(buf[1], 1, olen, fp2); + if(nlen != olen || memcmp(buf[0], buf[1], nlen)) { + retval = 0; + break; + } + } + nlen = fread(buf[1], 1, 1, fp2); + if(nlen) retval = 0; + + fclose(fp1); + fclose(fp2); + return retval; +} + /* * Copy file for real. */ @@ -265,9 +329,12 @@ real_copy(const char *src, const char *dst) { size_t len; int retval = 0; - fpsrc = fopen(src, "rb"); + if(identical_files(src, dst)) + return retval; /* Success, no need to copy for real. */ + + fpsrc = fopen(src, "r"); if(!fpsrc) { errno = EIO; return -1; } - fpdst = fopen(src, "wb"); + fpdst = asn1c_open_file(dst, "", 0); if(!fpdst) { fclose(fpsrc); errno = EIO; return -1; } while(!feof(fpsrc)) { diff --git a/libasn1compiler/asn1compiler.h b/libasn1compiler/asn1compiler.h index 817e06c9..d073517e 100644 --- a/libasn1compiler/asn1compiler.h +++ b/libasn1compiler/asn1compiler.h @@ -42,7 +42,7 @@ enum asn1c_flags { /* * Generate type_id_PR_member things identifiers of id_PR_member. */ - A1C_DOUBLE_IDENTIFIERS = 0x0100, + A1C_COMPOUND_NAMES = 0x0100, }; /*