how can i be certain that a file has copied exactly?

Giorgos Keramidas keramida at ceid.upatras.gr
Sat Dec 27 12:58:24 UTC 2008


On Sat, 27 Dec 2008 01:40:13 -0800, Gary Kline <kline at thought.org> wrote:
> howdy,
>
> in a word, YES, /usr/bin/cmp saved the save before i unlinked the
> oldfile.  here is the strangeness.  maybe you know, giorgos, or
> somebody else on-list.  At first--before i got smart and used your
> snprintf to simply /bin/cp and then unlink---yes, or /bin/mv, or
> simply rename()--- Before, while i creating via fgets/fputs a new
> file, everything went fine until i ran out of buffer space.  i
> increased to buf[4096] to buf[65535].  more files were successfully
> copied from dos\;5 to .dos/*.htm, actually.  suddenly, cmp caught a
> mismatch and the program exited.  a careful diff showed the err a
> something like line 3751.  my copy was missing a byte near the EOF:
>
> </body></html
>
> minus the closing ">"

There should be no problem when you copy a file using read() and write()
with _any_ buffer size.  Even a simple routine that reads byte by byte
and copies the file should work (a bit more of error checking is needed
wherever I have used a (void) cast but you get the idea):

    #include <stdio.h>
    #include <unistd.h>

    /*-
     * \brief copy a file, using stdio byte-level read and writes
     *
     * Copy the `fromname' file to the `toname' file, using only fgetc()
     * and fputc() operations from stdio.  The internals of stdio are
     * free, of course, to use larger read() and write() buffers but all
     * this should be "hidden" from the code of copyfile().
     *
     * \param fromname          The name of the source file to copy.
     * \param toname            The name of the destination file where
     *                          `fromname' will be copied to.
     *
     * \return                  Upon successful completion 0 is
     *                          returned.  Otherwise, EOF is returned
     *                          and the global variable errno is set to
     *                          indicate the error.
     */

    int
    copyfile(const char *fromname, const char *toname)
    {
            FILE *ifp;
            FILE *ofp;
            int ch;

            if ((ifp = fopen(fromname, "rb")) == NULL)
                    return -1;
            if ((ofp = fopen(toname, "wb")) == NULL) {
                    (void)fclose(ifp);
                    return -1;
            }

            while ((ch = fgetc(ifp)) != EOF) {
                    if (fputc(ch, ofp) == EOF)
                            break;
            }
            if (ferror(ifp) != 0 || ferror(ofp) != 0) {
                    (void)unlink(toname);
                    (void)fclose(ofp);
                    (void)fclose(ifp);
                    return -1;
            }

            if (fclose(ofp) == EOF) {
                    (void)fclose(ifp);
                    return -1;
            }
            if (fclose(ifp) == EOF) {
                    return -1;
            }

            return 0;
    }

So if you are seeing copy errors when you change the buffer size, you
are doing something odd with your buffers.  We would have to see the
actual code if you want more detailed help about possible buffer
handling bugs :)



More information about the freebsd-questions mailing list