home *** CD-ROM | disk | FTP | other *** search
- /* C.Frename: safe file rename which works across file systems */
-
- #include <stdio.h>
- #include "kernel.h"
-
- #include "utils.h"
-
- /* Rename a file. If a simple OS rename fails, the file is copied.
- * This allows renames across filing system boundaries.
- * If the destination filename exists, the function deletes it (even
- * if locked) first.
- * This function does its best to be totally paranoid about errors, and
- * returns failure if the rename does not work.
- * Returns 0 on success, 1 on failure.
- */
- int frename(const char *old, const char *new)
- {
- register int result;
- register int n;
- FILE *in, *out;
- _kernel_osfile_block blk;
- char buf[BUFSIZ];
-
- /* Check the new file. If it exists, and is not a directory,
- * unlock it (if necessary) and delete it.
- */
- result = _kernel_osfile (17, new, &blk);
-
- /* If the file is a directory, or an error occurred, return failure */
- if (result == 2 || result == _kernel_ERROR)
- return 1;
-
- /* If the file exists and is locked, unlock it */
- if (result == 1 && (blk.end & 0x0008) != 0)
- {
- blk.end &= ~0x0008;
- if (_kernel_osfile(4, new, &blk) == _kernel_ERROR)
- return 1;
- }
-
- /* If the file exists, delete it */
- if (result == 1 && _kernel_osfile(6, new, &blk) == _kernel_ERROR)
- return 1;
-
- /* Now try a simple OS rename */
- if (rename(old, new) == 0)
- return 0;
-
- /* No luck. Get the old file attributes (to ensure that it exists,
- * and is not locked, and for later copying to the new file).
- */
- result = _kernel_osfile (17, old, &blk);
-
- /* If the file is not a simple file, or an error occurred,
- * or the file is locked, return failure.
- */
- if (result != 1 || (blk.end & 0x0008) != 0)
- return 1;
-
- /* Now prepare to copy the file */
- if ((in = fopen(old, "rb")) == NULL)
- return 1;
-
- if ((out = fopen(new, "wb")) == NULL)
- {
- fclose(in);
- return 1;
- }
-
- /* Copy the file */
- while (!feof(in))
- {
- n = fread(buf, 1, BUFSIZ, in);
- if (ferror(in) || fwrite(buf, 1, n, out) != n)
- {
- fclose(in);
- fclose(out);
- remove(new);
- return 1;
- }
- }
-
- if (ferror(in) || fclose(in) == EOF || ferror(out) || fclose(out) == EOF)
- {
- remove(new);
- return 1;
- }
-
- /* Copy the file attributes across */
- if (_kernel_osfile(1, new, &blk) == _kernel_ERROR)
- {
- remove(new);
- return 1;
- }
-
- /* Delete the old file. The most likely case of error here
- * is renaming an open file. We left it a bit late to catch
- * this one, but we can't find out any earlier...
- */
- if (_kernel_osfile(6, old, &blk) == _kernel_ERROR)
- {
- remove(new);
- return 1;
- }
-
- return 0;
- }
-