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

/*
 * AppLock.vala
 *
 * Copyright 2012-2018 Tony George <teejeetech@gmail.com>
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 *
 *
 */

#include <glib-object.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
#include <gio/gio.h>
#include <glib/gi18n-lib.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_APP_LOCK (app_lock_get_type ())
#define APP_LOCK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_APP_LOCK, AppLock))
#define APP_LOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_APP_LOCK, AppLockClass))
#define IS_APP_LOCK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_APP_LOCK))
#define IS_APP_LOCK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_APP_LOCK))
#define APP_LOCK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_APP_LOCK, AppLockClass))

typedef struct _AppLock AppLock;
typedef struct _AppLockClass AppLockClass;
typedef struct _AppLockPrivate AppLockPrivate;
enum  {
	APP_LOCK_0_PROPERTY,
	APP_LOCK_NUM_PROPERTIES
};
static GParamSpec* app_lock_properties[APP_LOCK_NUM_PROPERTIES];
#define _g_free0(var) (var = (g_free (var), NULL))
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
#define _g_error_free0(var) ((var == NULL) ? NULL : (var = (g_error_free (var), NULL)))

struct _AppLock {
	GObject parent_instance;
	AppLockPrivate * priv;
	gchar* lock_file;
	gchar* lock_message;
};

struct _AppLockClass {
	GObjectClass parent_class;
};

static gpointer app_lock_parent_class = NULL;

VALA_EXTERN GType app_lock_get_type (void) G_GNUC_CONST ;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (AppLock, g_object_unref)
VALA_EXTERN gboolean app_lock_create (AppLock* self,
                          const gchar* app_name,
                          const gchar* message);
VALA_EXTERN gboolean tee_jee_file_system_dir_create (const gchar* dir_path,
                                         gboolean show_message);
VALA_EXTERN gchar* tee_jee_file_system_path_combine (const gchar* path1,
                                         const gchar* path2);
VALA_EXTERN gchar* tee_jee_file_system_file_read (const gchar* file_path);
VALA_EXTERN gchar* tee_jee_process_helper_get_process_exe_name (glong pid);
VALA_EXTERN void tee_jee_logging_log_msg (const gchar* message,
                              gboolean highlight);
static void app_lock_write_lock_file (AppLock* self,
                               const gchar* message);
VALA_EXTERN void tee_jee_logging_log_error (const gchar* message,
                                gboolean highlight,
                                gboolean is_warning);
VALA_EXTERN gboolean tee_jee_file_system_file_write (const gchar* file_path,
                                         const gchar* contents);
VALA_EXTERN void app_lock_remove (AppLock* self);
VALA_EXTERN AppLock* app_lock_new (void);
VALA_EXTERN AppLock* app_lock_construct (GType object_type);
static void app_lock_finalize (GObject * obj);
static GType app_lock_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 gssize _vala_array_length (gpointer array);

static gchar*
string_strip (const gchar* self)
{
	gchar* _result_ = NULL;
	gchar* _tmp0_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	_tmp0_ = g_strdup (self);
	_result_ = _tmp0_;
	g_strstrip (_result_);
	result = _result_;
	return result;
}

static glong
long_parse (const gchar* str,
            guint _base)
{
	glong result;
	g_return_val_if_fail (str != NULL, 0L);
	result = strtol (str, NULL, (gint) _base);
	return result;
}

static gboolean
string_contains (const gchar* self,
                 const gchar* needle)
{
	gchar* _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (needle != NULL, FALSE);
	_tmp0_ = strstr ((gchar*) self, (gchar*) needle);
	result = _tmp0_ != NULL;
	return result;
}

gboolean
app_lock_create (AppLock* self,
                 const gchar* app_name,
                 const gchar* message)
{
	gchar* lock_dir = NULL;
	gchar* _tmp0_;
	const gchar* _tmp1_;
	const gchar* _tmp2_;
	gchar* _tmp3_;
	gboolean _tmp33_ = FALSE;
	GError* _inner_error0_ = NULL;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (app_name != NULL, FALSE);
	g_return_val_if_fail (message != NULL, FALSE);
	_tmp0_ = g_strdup_printf ("/var/run/lock/%s", app_name);
	lock_dir = _tmp0_;
	_tmp1_ = lock_dir;
	tee_jee_file_system_dir_create (_tmp1_, FALSE);
	_tmp2_ = lock_dir;
	_tmp3_ = tee_jee_file_system_path_combine (_tmp2_, "lock");
	_g_free0 (self->lock_file);
	self->lock_file = _tmp3_;
	{
		GFile* file = NULL;
		const gchar* _tmp4_;
		GFile* _tmp5_;
		GFile* _tmp6_;
		_tmp4_ = self->lock_file;
		_tmp5_ = g_file_new_for_path (_tmp4_);
		file = _tmp5_;
		_tmp6_ = file;
		if (g_file_query_exists (_tmp6_, NULL)) {
			gchar* txt = NULL;
			const gchar* _tmp7_;
			gchar* _tmp8_;
			gchar* process_id = NULL;
			const gchar* _tmp9_;
			gchar** _tmp10_;
			gchar** _tmp11_;
			gchar** _tmp12_;
			gint _tmp12__length1;
			const gchar* _tmp13_;
			gchar* _tmp14_;
			gchar* _tmp15_;
			const gchar* _tmp16_;
			gchar** _tmp17_;
			gchar** _tmp18_;
			gchar** _tmp19_;
			gint _tmp19__length1;
			const gchar* _tmp20_;
			gchar* _tmp21_;
			glong pid = 0L;
			const gchar* _tmp22_;
			gchar* _tmp23_;
			gchar* _tmp24_;
			gboolean _tmp25_;
			_tmp7_ = self->lock_file;
			_tmp8_ = tee_jee_file_system_file_read (_tmp7_);
			txt = _tmp8_;
			_tmp9_ = txt;
			_tmp11_ = _tmp10_ = g_strsplit (_tmp9_, ";", 0);
			_tmp12_ = _tmp11_;
			_tmp12__length1 = _vala_array_length (_tmp10_);
			_tmp13_ = _tmp12_[0];
			_tmp14_ = string_strip (_tmp13_);
			_tmp15_ = _tmp14_;
			_tmp12_ = (_vala_array_free (_tmp12_, _tmp12__length1, (GDestroyNotify) g_free), NULL);
			process_id = _tmp15_;
			_tmp16_ = txt;
			_tmp18_ = _tmp17_ = g_strsplit (_tmp16_, ";", 0);
			_tmp19_ = _tmp18_;
			_tmp19__length1 = _vala_array_length (_tmp17_);
			_tmp20_ = _tmp19_[1];
			_tmp21_ = string_strip (_tmp20_);
			_g_free0 (self->lock_message);
			self->lock_message = _tmp21_;
			_tmp19_ = (_vala_array_free (_tmp19_, _tmp19__length1, (GDestroyNotify) g_free), NULL);
			_tmp22_ = process_id;
			pid = long_parse (_tmp22_, (guint) 0);
			_tmp23_ = tee_jee_process_helper_get_process_exe_name (pid);
			_tmp24_ = _tmp23_;
			_tmp25_ = string_contains (_tmp24_, "timeshift");
			_g_free0 (_tmp24_);
			if (_tmp25_) {
				gchar* _tmp26_;
				gchar* _tmp27_;
				gchar* _tmp28_;
				gchar* _tmp29_;
				_tmp26_ = g_strdup_printf (" (PID=%ld)", pid);
				_tmp27_ = _tmp26_;
				_tmp28_ = g_strconcat (_ ("Another instance of this application is running"), _tmp27_, NULL);
				_tmp29_ = _tmp28_;
				tee_jee_logging_log_msg (_tmp29_, FALSE);
				_g_free0 (_tmp29_);
				_g_free0 (_tmp27_);
				result = FALSE;
				_g_free0 (process_id);
				_g_free0 (txt);
				_g_object_unref0 (file);
				_g_free0 (lock_dir);
				return result;
			} else {
				GFile* _tmp30_;
				tee_jee_logging_log_msg (_ ("[Warning] Deleted invalid lock"), FALSE);
				_tmp30_ = file;
				g_file_delete (_tmp30_, NULL, &_inner_error0_);
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					_g_free0 (process_id);
					_g_free0 (txt);
					_g_object_unref0 (file);
					goto __catch0_g_error;
				}
				app_lock_write_lock_file (self, message);
				result = TRUE;
				_g_free0 (process_id);
				_g_free0 (txt);
				_g_object_unref0 (file);
				_g_free0 (lock_dir);
				return result;
			}
			_g_free0 (process_id);
			_g_free0 (txt);
		} else {
			app_lock_write_lock_file (self, message);
			result = TRUE;
			_g_object_unref0 (file);
			_g_free0 (lock_dir);
			return result;
		}
		_g_object_unref0 (file);
	}
	goto __finally0;
	__catch0_g_error:
	{
		GError* e = NULL;
		GError* _tmp31_;
		const gchar* _tmp32_;
		e = _inner_error0_;
		_inner_error0_ = NULL;
		_tmp31_ = e;
		_tmp32_ = _tmp31_->message;
		tee_jee_logging_log_error (_tmp32_, FALSE, FALSE);
		result = FALSE;
		_g_error_free0 (e);
		_g_free0 (lock_dir);
		return result;
	}
	__finally0:
	_g_free0 (lock_dir);
	g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
	g_clear_error (&_inner_error0_);
	return _tmp33_;
}

static void
app_lock_write_lock_file (AppLock* self,
                          const gchar* message)
{
	gchar* current_pid = NULL;
	gchar* _tmp0_;
	const gchar* _tmp1_;
	gchar* _tmp2_;
	gchar* _tmp3_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (message != NULL);
	_tmp0_ = g_strdup_printf ("%li", (glong) getpid ());
	current_pid = _tmp0_;
	_tmp1_ = self->lock_file;
	_tmp2_ = g_strdup_printf ("%s;%s", current_pid, message);
	_tmp3_ = _tmp2_;
	tee_jee_file_system_file_write (_tmp1_, _tmp3_);
	_g_free0 (_tmp3_);
	_g_free0 (current_pid);
}

void
app_lock_remove (AppLock* self)
{
	GError* _inner_error0_ = NULL;
	g_return_if_fail (self != NULL);
	{
		GFile* file = NULL;
		const gchar* _tmp0_;
		GFile* _tmp1_;
		GFile* _tmp2_;
		_tmp0_ = self->lock_file;
		_tmp1_ = g_file_new_for_path (_tmp0_);
		file = _tmp1_;
		_tmp2_ = file;
		if (g_file_query_exists (_tmp2_, NULL)) {
			GFile* _tmp3_;
			_tmp3_ = file;
			g_file_delete (_tmp3_, NULL, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				_g_object_unref0 (file);
				goto __catch0_g_error;
			}
		}
		_g_object_unref0 (file);
	}
	goto __finally0;
	__catch0_g_error:
	{
		GError* e = NULL;
		GError* _tmp4_;
		const gchar* _tmp5_;
		e = _inner_error0_;
		_inner_error0_ = NULL;
		_tmp4_ = e;
		_tmp5_ = _tmp4_->message;
		tee_jee_logging_log_error (_tmp5_, FALSE, FALSE);
		_g_error_free0 (e);
	}
	__finally0:
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
		g_clear_error (&_inner_error0_);
		return;
	}
}

AppLock*
app_lock_construct (GType object_type)
{
	AppLock * self = NULL;
	self = (AppLock*) g_object_new (object_type, NULL);
	return self;
}

AppLock*
app_lock_new (void)
{
	return app_lock_construct (TYPE_APP_LOCK);
}

static void
app_lock_class_init (AppLockClass * klass,
                     gpointer klass_data)
{
	app_lock_parent_class = g_type_class_peek_parent (klass);
	G_OBJECT_CLASS (klass)->finalize = app_lock_finalize;
}

static void
app_lock_instance_init (AppLock * self,
                        gpointer klass)
{
	gchar* _tmp0_;
	gchar* _tmp1_;
	_tmp0_ = g_strdup ("");
	self->lock_file = _tmp0_;
	_tmp1_ = g_strdup ("");
	self->lock_message = _tmp1_;
}

static void
app_lock_finalize (GObject * obj)
{
	AppLock * self;
	self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_APP_LOCK, AppLock);
	_g_free0 (self->lock_file);
	_g_free0 (self->lock_message);
	G_OBJECT_CLASS (app_lock_parent_class)->finalize (obj);
}

static GType
app_lock_get_type_once (void)
{
	static const GTypeInfo g_define_type_info = { sizeof (AppLockClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) app_lock_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (AppLock), 0, (GInstanceInitFunc) app_lock_instance_init, NULL };
	GType app_lock_type_id;
	app_lock_type_id = g_type_register_static (G_TYPE_OBJECT, "AppLock", &g_define_type_info, 0);
	return app_lock_type_id;
}

GType
app_lock_get_type (void)
{
	static volatile gsize app_lock_type_id__once = 0;
	if (g_once_init_enter (&app_lock_type_id__once)) {
		GType app_lock_type_id;
		app_lock_type_id = app_lock_get_type_once ();
		g_once_init_leave (&app_lock_type_id__once, app_lock_type_id);
	}
	return app_lock_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);
}

static gssize
_vala_array_length (gpointer array)
{
	gssize length;
	length = 0;
	if (array) {
		while (((gpointer*) array)[length]) {
			length++;
		}
	}
	return length;
}

