--- clit18/clit18/explode.c.bak 2004-07-04 06:33:52.000000000 +0300 +++ clit18/clit18/explode.c 2007-09-09 22:04:12.093094025 +0300 @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include "clit.h" #include "litlib.h" #include "manifest.h" @@ -453,7 +456,7 @@ int write_callback(void * v, U8 * pData, f = (FILE *)v; } r = fwrite(pData,1, nBytes,f); - if (r < 0) { + if (r != nBytes) { lit_error(ERR_W|ERR_LIBC,"fwrite of %d bytes failed!",nBytes); } return r; @@ -470,6 +473,8 @@ int write_htmlish_file(lit_file * litfi FILE * fOut; char * pathInternal; manifest_type * pmanifest, relative_manifest; + char tmpfn[4096]; + int fd; pmanifest = &manifest; p = NULL; @@ -503,11 +508,23 @@ int write_htmlish_file(lit_file * litfi if (status != 0) { status = -20; break;} pmanifest = &relative_manifest; } - - fOut = fopen(pathExternal, "w"); + + if (snprintf(tmpfn, sizeof(tmpfn), "%s.tmp.XXXXXX", pathExternal) >= sizeof(tmpfn)) { + lit_error(ERR_W, "too long filename %s", tmpfn); + status = -1; + break; + } + fd = mkstemp(tmpfn); + if (fd == -1) { + lit_error(ERR_LIBC|ERR_W,"mkstemp(%s) failed!", pathExternal); + status = -1; + break; + } + fOut = fdopen(fd, "w"); if (!fOut) { - lit_error(ERR_LIBC|ERR_W,"fopen(%s) failed!", pathExternal); - status = -1; + lit_error(ERR_LIBC|ERR_W,"fdopen(%s) failed!", tmpfn); + close(fd); + status = -1; break; } if (pathOriginal == NULL) { @@ -526,7 +543,7 @@ int write_htmlish_file(lit_file * litfi } if ((status > 0) && (status != nbytes)) { lit_error(ERR_R, -"Warning - Couldn't fully expand \"%s\", decoded %d out of %d.\n", +"ERROR - Couldn't fully expand \"%s\", decoded %d out of %d.\n", pathInternal, status, (int)nbytes); status = 1; } @@ -535,10 +552,25 @@ int write_htmlish_file(lit_file * litfi "ERROR - Failure during tag expansion of \"%s\" Code: %d!\n", pathInternal, status); } - else status = 0; - + else + status = 0; } while (0); - if (fOut != NULL) fclose(fOut); + if (fOut != NULL) { + if (fflush(fOut) || (fsync(fileno(fOut)) == -1 && errno != EINVAL) || + (fclose(fOut) == EOF)) { + lit_error(ERR_LIBC|ERR_W,"fclose(%s) failed!", pathExternal); + status = -1; + } + } + if (status == 0) { + if (rename(tmpfn, pathExternal) == -1) { + lit_error(ERR_R|ERR_LIBC, "ERROR - rename failed\n"); + unlink(tmpfn); + status = -1; + } + } else { + unlink(tmpfn); + } if (p) free(p); if (pathInternal) free(pathInternal); if (listAtoms) { lit_free_atoms(listAtoms); } @@ -549,29 +581,51 @@ int write_raw_file(lit_file * litfile,ch { int status; int nbytes; - U8 * p; - FILE * fOut; + U8 *p; + FILE *fOut; + char tmpfn[4096]; + int fd; status = lit_get_file(litfile,pathInternal,&p,&nbytes); if (status) return status; - fOut = fopen(pathExternal, "wb"); + if (snprintf(tmpfn, sizeof(tmpfn), "%s.tmp.XXXXXX", pathExternal) >= sizeof(tmpfn)) { + lit_error(ERR_W, "too long filename %s", tmpfn); + return -1; + } + fd = mkstemp(tmpfn); + if (fd == -1) { + lit_error(ERR_LIBC|ERR_W,"mkstemp(%s) failed!", pathExternal); + return -1; + } + fOut = fdopen(fd, "wb"); if (!fOut) { + lit_error(ERR_LIBC|ERR_W,"fdopen(%s) failed!", pathExternal); free(p); - lit_error(ERR_LIBC|ERR_W,"fopen(%s) failed!", pathExternal); + close(fd); return -1; } status = fwrite(p,1, nbytes,fOut); free(p); p = NULL; + if (fflush(fOut)) status = -1; - if (status < 0) { + if (status < 0 || (status != nbytes) || (fsync(fileno(fOut)) == -1 && errno != EINVAL)) { lit_error(ERR_W|ERR_LIBC,"Failed to write %d bytes.",nbytes); + fclose(fOut); + unlink(tmpfn); return status; } - if (status != nbytes) { - lit_error(ERR_W,"Partial write, wrote %d out of %d.",status,nbytes); + if (fclose(fOut) == EOF) { + lit_error(ERR_W|ERR_LIBC,"Failed to close %s.", pathExternal); + unlink(tmpfn); return -1; } - fclose(fOut); + + if (rename(tmpfn, pathExternal) == -1) { + lit_error(ERR_R|ERR_LIBC, "ERROR - rename failed\n"); + unlink(tmpfn); + return -1; + } + return 0; } --- clit18/clit18/transmute.c.bak 2007-09-09 19:27:26.328349000 +0300 +++ clit18/clit18/transmute.c 2007-09-09 21:48:07.859382473 +0300 @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include "litlib.h" extern char * writingFilename; @@ -40,11 +42,22 @@ int transmute_lit(lit_file * litfile, ch int drm_size = 0; FILE * fOut; lit_file outlit; + char tmpfn[4096]; + int fd; writingFilename = newlitfile; - fOut = fopen(newlitfile,"wb"); + if (snprintf(tmpfn, sizeof(tmpfn), "%s.tmp.XXXXXX", newlitfile) >= sizeof(tmpfn)) { + lit_error(ERR_W, "too long filename %s", tmpfn); + return -1; + } + fd = mkstemp(tmpfn); + if (fd == -1) { + lit_error(ERR_LIBC|ERR_W,"mkstemp(%s) failed!", tmpfn); + return -1; + } + fOut = fdopen(fd, "wb"); if (!fOut) { - lit_error(ERR_W|ERR_LIBC,"Unable to open \"%s\"!", newlitfile); + lit_error(ERR_W|ERR_LIBC,"Unable to open \"%s\"!", tmpfn); return -1; } newlevel = 1; @@ -79,6 +92,36 @@ int transmute_lit(lit_file * litfile, ch if (drm_data) free(drm_data); lit_close(&outlit); + + if (status == 0) { + if (fflush(fOut) == EOF) { + unlink(tmpfn); + lit_error(ERR_W|ERR_LIBC,"Unable to write \"%s\"!", tmpfn); + fclose(fOut); + return -1; + } + + if (fsync(fileno(fOut)) == -1 && (errno != EINVAL)) { + lit_error(ERR_W|ERR_LIBC,"Unable to fsync \"%s\"", tmpfn); + unlink(tmpfn); + return -1; + } + + if (fclose(fOut) == EOF) { + unlink(tmpfn); + lit_error(ERR_W|ERR_LIBC,"Unable to close \"%s\"!", tmpfn); + return -1; + } + + if (rename(tmpfn, newlitfile) == -1) { + unlink(tmpfn); + lit_error(ERR_W|ERR_LIBC,"Unable to rename \"%s\" to \"%s\"", tmpfn, newlitfile); + return -1; + } + } else { + unlink(tmpfn); + } + return status; }