aboutsummaryrefslogtreecommitdiffstats
path: root/libparc/parc/algol/parc_File.c
diff options
context:
space:
mode:
Diffstat (limited to 'libparc/parc/algol/parc_File.c')
-rw-r--r--libparc/parc/algol/parc_File.c262
1 files changed, 262 insertions, 0 deletions
diff --git a/libparc/parc/algol/parc_File.c b/libparc/parc/algol/parc_File.c
new file mode 100644
index 00000000..2ab307a2
--- /dev/null
+++ b/libparc/parc/algol/parc_File.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2017 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ */
+#include <config.h>
+
+#ifndef _XOPEN_SOURCE
+#define _XOPEN_SOURCE 500
+#endif //_XOPEN_SOURCE 500
+
+#ifndef __USE_XOPEN_EXTENDED
+#define __USE_XOPEN_EXTENDED
+#endif //__USE_XOPEN_EXTENDED
+
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+
+#include <ftw.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <string.h>
+#include <errno.h>
+
+#include <LongBow/runtime.h>
+
+#include <parc/algol/parc_Object.h>
+#include <parc/algol/parc_PathName.h>
+#include <parc/algol/parc_File.h>
+#include <parc/algol/parc_Memory.h>
+
+
+struct parc_file {
+ PARCPathName *pathName;
+};
+
+static bool
+_parcFile_Destructor(PARCFile **filePtr)
+{
+ PARCFile *file = *filePtr;
+
+ parcPathName_Release(&file->pathName);
+
+ return true;
+}
+
+parcObject_Override(PARCFile, PARCObject,
+ .destructor = (PARCObjectDestructor *) _parcFile_Destructor,
+ .toString = (PARCObjectToString *) parcFile_ToString);
+
+void
+parcFile_AssertValid(const PARCFile *instance)
+{
+ trapIllegalValueIf(instance == NULL, "Parameter must be a non-null pointer to a valid PARCFile.");
+ trapIllegalValueIf(instance->pathName == NULL, "PARCFile cannot have a NULL path-name");
+}
+
+PARCFile *
+parcFile_Create(const char *path)
+{
+ PARCFile *result = NULL;
+
+ PARCPathName *pathName = parcPathName_Parse(path);
+ if (pathName != NULL) {
+ result = parcObject_CreateInstance(PARCFile);
+ if (result != NULL) {
+ result->pathName = pathName;
+ } else {
+ parcPathName_Release(&pathName);
+ }
+ }
+
+ return result;
+}
+
+PARCFile *
+parcFile_CreateChild(const PARCFile *parent, char *fileName)
+{
+ PARCFile *result = NULL;
+
+ PARCPathName *childPath = parcPathName_Append(parcPathName_Copy(parent->pathName), fileName);
+
+ if (childPath != NULL) {
+ result = parcObject_CreateInstance(PARCFile);
+ if (result != NULL) {
+ result->pathName = childPath;
+ }
+ }
+
+ return result;
+}
+
+parcObject_ImplementAcquire(parcFile, PARCFile);
+
+parcObject_ImplementRelease(parcFile, PARCFile);
+
+bool
+parcFile_CreateNewFile(const PARCFile *file)
+{
+ parcFile_OptionalAssertValid(file);
+
+ bool result = false;
+
+ char *string = parcPathName_ToString(file->pathName);
+
+ int fd = open(string, O_EXCL | O_CREAT | O_TRUNC, 0666);
+ if (fd != -1) {
+ close(fd);
+ result = true;
+ }
+ parcMemory_Deallocate((void **) &string);
+
+ return result;
+}
+
+bool
+parcFile_Mkdir(const PARCFile *file)
+{
+ parcFile_OptionalAssertValid(file);
+
+ char *string = parcPathName_ToString(file->pathName);
+ bool result = (mkdir(string, 0777) == 0);
+ parcMemory_Deallocate((void **) &string);
+
+ return result;
+}
+
+bool
+parcFile_Exists(const PARCFile *file)
+{
+ struct stat statbuf;
+
+ char *string = parcPathName_ToString(file->pathName);
+ bool result = stat(string, &statbuf) == 0;
+ parcMemory_Deallocate((void **) &string);
+
+ return result;
+}
+
+bool
+parcFile_IsDirectory(const PARCFile *file)
+{
+ bool result = false;
+ struct stat statbuf;
+
+ char *string = parcPathName_ToString(file->pathName);
+ if (stat(string, &statbuf) == 0) {
+ result = S_ISDIR(statbuf.st_mode);
+ }
+ parcMemory_Deallocate((void **) &string);
+
+ return result;
+}
+
+static int
+_deleteNode(const char *path, const struct stat *stat, int flag, struct FTW *ftwbuf)
+{
+ int result = 0;
+
+ if (flag == FTW_DP) { // directory in post-order
+ result = rmdir(path);
+ } else {
+ result = unlink(path);
+ }
+ return result;
+}
+
+/**
+ * @function parcFile_Delete
+ * @abstract Deletes the file or directory
+ * @discussion
+ *
+ * @param <#param1#>
+ * @return true if everything deleted, false otherwise
+ */
+bool
+parcFile_Delete(const PARCFile *file)
+{
+ char *string = parcPathName_ToString(file->pathName);
+
+ // only allow under tmp
+ assertTrue(strncmp(string, "/tmp/", 5) == 0,
+ "Path must begin with /tmp/: %s", string);
+ // dont allow ".."
+ assertNull(strstr(string, ".."), "Path cannot have .. in it: %s", string);
+
+ bool result = false;
+ if (parcFile_IsDirectory(file)) {
+ // depth first, dont't follow symlinks, do not cross mount points.
+ int flags = FTW_DEPTH | FTW_PHYS | FTW_MOUNT;
+
+ // maximum 20 fds open at a time
+ int maximumFileDescriptors = 20;
+
+ int failure = nftw(string, _deleteNode, maximumFileDescriptors, flags);
+ assertFalse(failure, "Error on recursive delete: (%d) %s", errno, strerror(errno));
+
+ result = failure == false;
+ } else {
+ result = (unlink(string) == 0);
+ }
+
+ parcMemory_Deallocate((void **) &string);
+
+ return result;
+}
+
+PARCBufferComposer *
+parcFile_BuildString(const PARCFile *file, PARCBufferComposer *composer)
+{
+ parcPathName_BuildString(file->pathName, composer);
+
+ return composer;
+}
+
+char *
+parcFile_ToString(const PARCFile *file)
+{
+ PARCBufferComposer *composer = parcBufferComposer_Create();
+ parcFile_BuildString(file, composer);
+
+ PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer);
+ char *result = parcBuffer_ToString(tempBuffer);
+ parcBuffer_Release(&tempBuffer);
+
+ parcBufferComposer_Release(&composer);
+
+ return result;
+}
+
+size_t
+parcFile_GetFileSize(const PARCFile *file)
+{
+ size_t fileSize = 0;
+
+ char *fname = parcPathName_ToString(file->pathName);
+
+ struct stat st;
+
+ if (stat(fname, &st) == 0) {
+ fileSize = st.st_size;
+ }
+
+ parcMemory_Deallocate(&fname);
+
+ return fileSize;
+}