/* RestoreFileTester.c generated by valac 0.56.18-dirty, the Vala compiler
 * generated from RestoreFileTester.vala, do not modify */

/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*-
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 * SPDX-FileCopyrightText: Michael Terry
 */

#define _GNU_SOURCE

#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include "deja.h"
#include <gio/gio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>

#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif
#if !defined(VALA_EXTERN)
#if defined(_MSC_VER)
#define VALA_EXTERN __declspec(dllexport) extern
#elif __GNUC__ >= 4
#define VALA_EXTERN __attribute__((visibility("default"))) extern
#else
#define VALA_EXTERN extern
#endif
#endif

#define TYPE_RESTORE_FILE_TESTER (restore_file_tester_get_type ())
#define RESTORE_FILE_TESTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_RESTORE_FILE_TESTER, RestoreFileTester))
#define RESTORE_FILE_TESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_RESTORE_FILE_TESTER, RestoreFileTesterClass))
#define IS_RESTORE_FILE_TESTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_RESTORE_FILE_TESTER))
#define IS_RESTORE_FILE_TESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_RESTORE_FILE_TESTER))
#define RESTORE_FILE_TESTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_RESTORE_FILE_TESTER, RestoreFileTesterClass))

typedef struct _RestoreFileTester RestoreFileTester;
typedef struct _RestoreFileTesterClass RestoreFileTesterClass;
typedef struct _RestoreFileTesterPrivate RestoreFileTesterPrivate;
enum  {
	RESTORE_FILE_TESTER_0_PROPERTY,
	RESTORE_FILE_TESTER_NUM_PROPERTIES
};
static GParamSpec* restore_file_tester_properties[RESTORE_FILE_TESTER_NUM_PROPERTIES];
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))

struct _RestoreFileTester {
	GObject parent_instance;
	RestoreFileTesterPrivate * priv;
};

struct _RestoreFileTesterClass {
	GObjectClass parent_class;
};

static gpointer restore_file_tester_parent_class = NULL;

VALA_EXTERN GType restore_file_tester_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (RestoreFileTester, g_object_unref)
VALA_EXTERN GList* restore_file_tester_get_bad_paths (const gchar* prefix,
                                          DejaDupFileTree* tree,
                                          gboolean* all_bad,
                                          GList* files);
static void _vala_array_add5 (DejaDupFileTreeNode** * array,
                       gint* length,
                       gint* size,
                       DejaDupFileTreeNode* value);
static void restore_file_tester_recurse_node (const gchar* prefix,
                                       DejaDupFileTree* tree,
                                       DejaDupFileTreeNode* node,
                                       gboolean* all_bad,
                                       GList** bad_paths);
static gboolean restore_file_tester_can_restore (const gchar* path,
                                          gboolean* exists);
VALA_EXTERN RestoreFileTester* restore_file_tester_new (void);
VALA_EXTERN RestoreFileTester* restore_file_tester_construct (GType object_type);
static GType restore_file_tester_get_type_once (void);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);

static gpointer
_g_object_ref0 (gpointer self)
{
	return self ? g_object_ref (self) : NULL;
}

static void
_vala_array_add5 (DejaDupFileTreeNode** * array,
                  gint* length,
                  gint* size,
                  DejaDupFileTreeNode* value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (DejaDupFileTreeNode*, *array, (*size) + 1);
	}
	(*array)[(*length)++] = value;
	(*array)[*length] = NULL;
}

GList*
restore_file_tester_get_bad_paths (const gchar* prefix,
                                   DejaDupFileTree* tree,
                                   gboolean* all_bad,
                                   GList* files)
{
	gboolean _vala_all_bad = FALSE;
	DejaDupFileTreeNode** roots = NULL;
	DejaDupFileTreeNode** _tmp0_;
	gint roots_length1;
	gint _roots_size_;
	GList* bad_paths = NULL;
	DejaDupFileTreeNode** _tmp11_;
	gint _tmp11__length1;
	GList* result;
	g_return_val_if_fail (prefix != NULL, NULL);
	g_return_val_if_fail (tree != NULL, NULL);
	_vala_all_bad = TRUE;
	_tmp0_ = g_new0 (DejaDupFileTreeNode*, 0 + 1);
	roots = _tmp0_;
	roots_length1 = 0;
	_roots_size_ = roots_length1;
	{
		GList* file_collection = NULL;
		GList* file_it = NULL;
		file_collection = files;
		for (file_it = file_collection; file_it != NULL; file_it = file_it->next) {
			GFile* _tmp1_;
			GFile* file = NULL;
			_tmp1_ = _g_object_ref0 ((GFile*) file_it->data);
			file = _tmp1_;
			{
				DejaDupFileTreeNode* node = NULL;
				GFile* _tmp2_;
				DejaDupFileTreeNode* _tmp3_;
				DejaDupFileTreeNode* _tmp4_;
				_tmp2_ = file;
				_tmp3_ = deja_dup_file_tree_file_to_node (tree, _tmp2_, FALSE);
				node = _tmp3_;
				_tmp4_ = node;
				if (_tmp4_ != NULL) {
					DejaDupFileTreeNode* _tmp5_;
					DejaDupFileTreeNode* _tmp6_;
					_tmp5_ = node;
					_tmp6_ = _g_object_ref0 (_tmp5_);
					_vala_array_add5 (&roots, &roots_length1, &_roots_size_, _tmp6_);
				}
				_g_object_unref0 (node);
				_g_object_unref0 (file);
			}
		}
	}
	if (g_list_length (files) == ((guint) 0)) {
		DejaDupFileTreeNode* _tmp7_;
		DejaDupFileTreeNode* _tmp8_;
		DejaDupFileTreeNode* _tmp9_;
		DejaDupFileTreeNode** _tmp10_;
		_tmp7_ = deja_dup_file_tree_get_root (tree);
		_tmp8_ = _tmp7_;
		_tmp9_ = _g_object_ref0 (_tmp8_);
		_tmp10_ = g_new0 (DejaDupFileTreeNode*, 1 + 1);
		_tmp10_[0] = _tmp9_;
		roots = (_vala_array_free (roots, roots_length1, (GDestroyNotify) g_object_unref), NULL);
		roots = _tmp10_;
		roots_length1 = 1;
		_roots_size_ = roots_length1;
	}
	bad_paths = NULL;
	_tmp11_ = roots;
	_tmp11__length1 = roots_length1;
	{
		DejaDupFileTreeNode** node_collection = NULL;
		gint node_collection_length1 = 0;
		gint _node_collection_size_ = 0;
		gint node_it = 0;
		node_collection = _tmp11_;
		node_collection_length1 = _tmp11__length1;
		for (node_it = 0; node_it < node_collection_length1; node_it = node_it + 1) {
			DejaDupFileTreeNode* _tmp12_;
			DejaDupFileTreeNode* node = NULL;
			_tmp12_ = _g_object_ref0 (node_collection[node_it]);
			node = _tmp12_;
			{
				DejaDupFileTreeNode* _tmp13_;
				_tmp13_ = node;
				restore_file_tester_recurse_node (prefix, tree, _tmp13_, &_vala_all_bad, &bad_paths);
				_g_object_unref0 (node);
			}
		}
	}
	result = bad_paths;
	roots = (_vala_array_free (roots, roots_length1, (GDestroyNotify) g_object_unref), NULL);
	if (all_bad) {
		*all_bad = _vala_all_bad;
	}
	return result;
}

static void
restore_file_tester_recurse_node (const gchar* prefix,
                                  DejaDupFileTree* tree,
                                  DejaDupFileTreeNode* node,
                                  gboolean* all_bad,
                                  GList** bad_paths)
{
	gchar* resolved = NULL;
	gboolean exists = FALSE;
	const gchar* _tmp7_;
	gboolean _tmp8_ = FALSE;
	gboolean _tmp9_;
	GHashTable* _tmp14_;
	GHashTable* _tmp15_;
	GList* _tmp16_;
	g_return_if_fail (prefix != NULL);
	g_return_if_fail (tree != NULL);
	g_return_if_fail (node != NULL);
	if (g_strcmp0 (prefix, "/") == 0) {
		gchar* _tmp0_;
		gchar* _tmp1_;
		gchar* _tmp2_;
		_tmp0_ = deja_dup_file_tree_node_to_path (tree, node);
		_tmp1_ = _tmp0_;
		_tmp2_ = g_build_filename (prefix, _tmp1_, NULL);
		_g_free0 (resolved);
		resolved = _tmp2_;
		_g_free0 (_tmp1_);
	} else {
		const gchar* _tmp3_;
		const gchar* _tmp4_;
		gchar* _tmp5_;
		const gchar* _tmp6_;
		_tmp3_ = deja_dup_file_tree_node_get_filename (node);
		_tmp4_ = _tmp3_;
		_tmp5_ = g_build_filename (prefix, _tmp4_, NULL);
		_g_free0 (resolved);
		resolved = _tmp5_;
		_tmp6_ = resolved;
		prefix = _tmp6_;
	}
	_tmp7_ = resolved;
	_tmp9_ = restore_file_tester_can_restore (_tmp7_, &_tmp8_);
	exists = _tmp8_;
	if (!_tmp9_) {
		const gchar* _tmp10_;
		gchar* _tmp11_;
		_tmp10_ = resolved;
		_tmp11_ = g_strdup (_tmp10_);
		*bad_paths = g_list_append (*bad_paths, _tmp11_);
	} else {
		GFileType _tmp12_;
		GFileType _tmp13_;
		_tmp12_ = deja_dup_file_tree_node_get_kind (node);
		_tmp13_ = _tmp12_;
		if (_tmp13_ != G_FILE_TYPE_DIRECTORY) {
			*all_bad = FALSE;
		}
	}
	if (!exists) {
		_g_free0 (resolved);
		return;
	}
	_tmp14_ = deja_dup_file_tree_node_get_children (node);
	_tmp15_ = _tmp14_;
	_tmp16_ = g_hash_table_get_values (_tmp15_);
	{
		GList* child_collection = NULL;
		GList* child_it = NULL;
		child_collection = _tmp16_;
		for (child_it = child_collection; child_it != NULL; child_it = child_it->next) {
			DejaDupFileTreeNode* child = NULL;
			child = (DejaDupFileTreeNode*) child_it->data;
			{
				DejaDupFileTreeNode* _tmp17_;
				_tmp17_ = child;
				restore_file_tester_recurse_node (prefix, tree, _tmp17_, all_bad, bad_paths);
			}
		}
		(child_collection == NULL) ? NULL : (child_collection = (g_list_free (child_collection), NULL));
	}
	_g_free0 (resolved);
}

static gboolean
restore_file_tester_can_restore (const gchar* path,
                                 gboolean* exists)
{
	gboolean _vala_exists = FALSE;
	gint fd = 0;
	gboolean result;
	g_return_val_if_fail (path != NULL, FALSE);
	_vala_exists = TRUE;
	fd = open (path, (O_WRONLY | O_NONBLOCK) | O_NOFOLLOW, (mode_t) 0);
	if (fd < 0) {
		gboolean _tmp0_ = FALSE;
		gboolean _tmp1_ = FALSE;
		gboolean _tmp2_ = FALSE;
		if (errno == EACCES) {
			_tmp2_ = TRUE;
		} else {
			_tmp2_ = errno == ENOTDIR;
		}
		if (_tmp2_) {
			_tmp1_ = TRUE;
		} else {
			_tmp1_ = errno == EPERM;
		}
		if (_tmp1_) {
			_tmp0_ = TRUE;
		} else {
			_tmp0_ = errno == EROFS;
		}
		if (_tmp0_) {
			result = FALSE;
			if (exists) {
				*exists = _vala_exists;
			}
			return result;
		} else {
			if (errno == ENOENT) {
				gchar* iter = NULL;
				gchar* _tmp3_;
				gint can_access = 0;
				_vala_exists = FALSE;
				_tmp3_ = g_strdup (path);
				iter = _tmp3_;
				can_access = -1;
				while (TRUE) {
					gboolean _tmp4_ = FALSE;
					const gchar* _tmp5_;
					gchar* _tmp6_;
					const gchar* _tmp7_;
					if (can_access != 0) {
						_tmp4_ = errno == ENOENT;
					} else {
						_tmp4_ = FALSE;
					}
					if (!_tmp4_) {
						break;
					}
					_tmp5_ = iter;
					_tmp6_ = g_path_get_dirname (_tmp5_);
					_g_free0 (iter);
					iter = _tmp6_;
					_tmp7_ = iter;
					can_access = access (_tmp7_, W_OK | X_OK);
				}
				if (can_access != 0) {
					result = FALSE;
					_g_free0 (iter);
					if (exists) {
						*exists = _vala_exists;
					}
					return result;
				}
				_g_free0 (iter);
			}
		}
	} else {
		close (fd);
	}
	result = TRUE;
	if (exists) {
		*exists = _vala_exists;
	}
	return result;
}

RestoreFileTester*
restore_file_tester_construct (GType object_type)
{
	RestoreFileTester * self = NULL;
	self = (RestoreFileTester*) g_object_new (object_type, NULL);
	return self;
}

RestoreFileTester*
restore_file_tester_new (void)
{
	return restore_file_tester_construct (TYPE_RESTORE_FILE_TESTER);
}

static void
restore_file_tester_class_init (RestoreFileTesterClass * klass,
                                gpointer klass_data)
{
	restore_file_tester_parent_class = g_type_class_peek_parent (klass);
}

static void
restore_file_tester_instance_init (RestoreFileTester * self,
                                   gpointer klass)
{
}

 G_GNUC_NO_INLINE static GType
restore_file_tester_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (RestoreFileTesterClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) restore_file_tester_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (RestoreFileTester), 0, (GInstanceInitFunc) restore_file_tester_instance_init, NULL };
	GType restore_file_tester_type_id;
	restore_file_tester_type_id = g_type_register_static (G_TYPE_OBJECT, "RestoreFileTester", &g_define_type_info, 0);
	return restore_file_tester_type_id;
}

GType
restore_file_tester_get_type (void)
{
	static gsize restore_file_tester_type_id__once = 0;
	if (g_once_init_enter (&restore_file_tester_type_id__once)) {
		GType restore_file_tester_type_id;
		restore_file_tester_type_id = restore_file_tester_get_type_once ();
		g_once_init_leave (&restore_file_tester_type_id__once, restore_file_tester_type_id);
	}
	return restore_file_tester_type_id__once;
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

