From 7f6002caba3f0a6749820c2772161caf55b8d267 Mon Sep 17 00:00:00 2001 From: neonloop Date: Fri, 7 May 2021 20:00:12 +0000 Subject: Initial commit (uqm-0.8.0) --- src/libs/file/files.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/libs/file/files.c (limited to 'src/libs/file/files.c') diff --git a/src/libs/file/files.c b/src/libs/file/files.c new file mode 100644 index 0000000..5ce7dac --- /dev/null +++ b/src/libs/file/files.c @@ -0,0 +1,165 @@ +/* + * 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 of the License, 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, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +// Contains code handling files + +#include +#include +#include +#include +#include +#include "port.h" +#include "libs/uio.h" +#include "config.h" +#include "types.h" +#include "filintrn.h" +#include "libs/memlib.h" +#include "libs/log.h" + +static int copyError(uio_Handle *srcHandle, uio_Handle *dstHandle, + uio_DirHandle *unlinkHandle, const char *unlinkPath, uint8 *buf); + +bool +fileExists (const char *name) +{ + return access (name, F_OK) == 0; +} + +bool +fileExists2(uio_DirHandle *dir, const char *fileName) +{ + uio_Stream *stream; + + stream = uio_fopen (dir, fileName, "rb"); + if (stream == NULL) + return 0; + + uio_fclose (stream); + return 1; +} + +/* + * Copy a file with path srcName to a file with name newName. + * If the destination already exists, the operation fails. + * Links are followed. + * Special files (fifos, char devices, block devices, etc) will be + * read as long as there is data available and the destination will be + * a regular file with that data. + * The new file will have the same permissions as the old. + * If an error occurs during copying, an attempt will be made to + * remove the copy. + */ +int +copyFile (uio_DirHandle *srcDir, const char *srcName, + uio_DirHandle *dstDir, const char *newName) +{ + uio_Handle *src, *dst; + struct stat sb; +#define BUFSIZE 65536 + uint8 *buf, *bufPtr; + ssize_t numInBuf, numWritten; + + src = uio_open (srcDir, srcName, O_RDONLY +#ifdef WIN32 + | O_BINARY +#endif + , 0); + if (src == NULL) + return -1; + + if (uio_fstat (src, &sb) == -1) + return copyError (src, NULL, NULL, NULL, NULL); + + dst = uio_open (dstDir, newName, O_WRONLY | O_CREAT | O_EXCL +#ifdef WIN32 + | O_BINARY +#endif + , sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + if (dst == NULL) + return copyError (src, NULL, NULL, NULL, NULL); + + buf = HMalloc(BUFSIZE); + // This was originally a statically allocated buffer, + // but as this function might be run from a thread with + // a small stack, this is better. + while (1) + { + numInBuf = uio_read (src, buf, BUFSIZE); + if (numInBuf == -1) + { + if (errno == EINTR) + continue; + return copyError (src, dst, dstDir, newName, buf); + } + if (numInBuf == 0) + break; + + bufPtr = buf; + do + { + numWritten = uio_write (dst, bufPtr, numInBuf); + if (numWritten == -1) + { + if (errno == EINTR) + continue; + return copyError (src, dst, dstDir, newName, buf); + } + numInBuf -= numWritten; + bufPtr += numWritten; + } while (numInBuf > 0); + } + + HFree (buf); + uio_close (src); + uio_close (dst); + errno = 0; + return 0; +} + +/* + * Closes srcHandle if it's not -1. + * Closes dstHandle if it's not -1. + * Removes unlinkpath from the unlinkHandle dir if it's not NULL. + * Frees 'buf' if not NULL. + * Always returns -1. + * errno is what was before the call. + */ +static int +copyError(uio_Handle *srcHandle, uio_Handle *dstHandle, + uio_DirHandle *unlinkHandle, const char *unlinkPath, uint8 *buf) +{ + int savedErrno; + + savedErrno = errno; + + log_add (log_Debug, "Error while copying: %s", strerror (errno)); + + if (srcHandle != NULL) + uio_close (srcHandle); + + if (dstHandle != NULL) + uio_close (dstHandle); + + if (unlinkPath != NULL) + uio_unlink (unlinkHandle, unlinkPath); + + if (buf != NULL) + HFree(buf); + + errno = savedErrno; + return -1; +} + -- cgit v1.2.3