Skip to content

Commit

Permalink
refactor: Migrate from linked list to array as suggested in glib doc
Browse files Browse the repository at this point in the history
  • Loading branch information
abelcheung committed Dec 18, 2023
1 parent 60064f8 commit b2c38db
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 48 deletions.
1 change: 0 additions & 1 deletion src/rifiuti.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

static exitcode exit_status = EXIT_OK;
extern char *legacy_encoding;
extern GSList *filelist;
extern metarecord *meta;


Expand Down
85 changes: 55 additions & 30 deletions src/utils-linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,20 @@ G_DEFINE_QUARK (rifiuti-misc-error-quark, rifiuti_misc_error)
* @param separator Field separator in desired line
* @param needle_pos Field number where needle is supposed to be
* @param result_pos Field number of data we want
* @return GSList of desired data
* @note This routine does not require all lines to have same separator; result could be extracted as long as the particular matching line has all the right conditions.
* @return Desired search result in `GPtrArray`
* @note This routine does not require all lines to have same
* separator; result could be extracted as long as the
* particular matching line has all the right conditions.
*/
static GSList *
_search_delimited_text (const char *haystack,
const char *needle,
const char *sep,
gsize needle_pos,
gsize result_pos)
static GPtrArray *
_search_delimited_text (const char *haystack,
const char *needle,
const char *sep,
gsize needle_pos,
gsize result_pos)
{
GSList *result = NULL;
GPtrArray *result = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);

char **lines = g_strsplit (haystack, "\n", 0);
for (gsize i = 0; i < g_strv_length (lines); i++)
{
Expand All @@ -38,9 +41,12 @@ _search_delimited_text (const char *haystack,
g_debug ("Found potential match '%s' in line '%s'", needle, lines[i]);
char **fields = g_strsplit (g_strchomp (lines[i]), sep, 0);
gsize nfields = g_strv_length (fields);
if (nfields >= needle_pos && nfields > result_pos)
if (g_strcmp0 (fields[needle_pos], needle) == 0)
result = g_slist_prepend (result, g_strdup (fields[result_pos]));
if (nfields > needle_pos &&
nfields > result_pos &&
g_strcmp0 (fields[needle_pos], needle) == 0)
{
g_ptr_array_add (result, g_strdup (fields[result_pos]));
}
g_strfreev (fields);
}

Expand Down Expand Up @@ -111,10 +117,16 @@ _get_user_sid (GError **error)
}


static GSList *
/**
* @brief Check mount points for potential Windows drive
* @param error Location to store `GError` upon problem
* @return `GPtrArray` containing found mount points,
* or `NULL` if problem arises
*/
static GPtrArray *
_probe_mounts (GError **error)
{
GSList *result = NULL;
GPtrArray *result;
GError *read_error = NULL;
gsize len;
char *mounts_data = NULL;
Expand All @@ -130,44 +142,55 @@ _probe_mounts (GError **error)
}

result = _search_delimited_text (
(const char *)mounts_data, fstype, " ", 2, 1);
(const char *) mounts_data, fstype, " ", 2, 1);
g_free (mounts_data);
return result;
}


/**
* @brief Probe for possible Windows Recycle Bin under WSL Linux
* @return List of possible Windows paths to be checked
* @param error Location to store `GError` when problem arises
* @return List of possible Windows paths in `GPtrArray`
*/
GSList *
GPtrArray *
enumerate_drive_bins (GError **error)
{
GSList *result = NULL, *mnt_pts;
GPtrArray *mnt_pts, *result;
char *sid;

if (NULL == (sid = _get_user_sid (error)))
return NULL;

if (NULL == (mnt_pts = _probe_mounts (error)))
mnt_pts = _probe_mounts (error);
if (mnt_pts == NULL)
return NULL;
if (mnt_pts->len == 0)
{
g_ptr_array_free (mnt_pts, TRUE);
return NULL;
}

result = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);

for (GSList *ptr = mnt_pts; ptr != NULL; ptr = ptr->next)
for (gsize i = 0; i < mnt_pts->len; i++)
{
char *full_rbin_path = g_build_filename (
(char *) ptr->data, "$Recycle.bin", sid, NULL);
(char *) (mnt_pts->pdata[i]), "$Recycle.bin", sid, NULL);
if (g_file_test (full_rbin_path, G_FILE_TEST_EXISTS))
result = g_slist_prepend (result, full_rbin_path);
g_ptr_array_add (result, full_rbin_path);
else
g_free (full_rbin_path);
}
g_ptr_array_free (mnt_pts, TRUE);

if (result == NULL)
if (result->len == 0) {
g_set_error_literal (error, R2_MISC_ERROR,
R2_MISC_ERROR_ENUMERATE_MNT,
"No recycle bin found on system");
g_slist_free_full (mnt_pts, (GDestroyNotify) g_free);

g_ptr_array_free (result, TRUE);
result = NULL;
}
return result;
}

Expand All @@ -183,6 +206,7 @@ windows_product_name (void)
char *cmd_out = NULL, *cmd_err = NULL, *result = NULL;
int exit_code;
GError *error = NULL;
GPtrArray *search_result;

if (FALSE == g_spawn_command_line_sync(
cmd, &cmd_out, &cmd_err, &exit_code, &error))
Expand All @@ -199,13 +223,14 @@ windows_product_name (void)

g_debug ("reg.exe output: %s", cmd_out);

GSList *searches = _search_delimited_text (
search_result = _search_delimited_text (
(const char *)cmd_out, "ProductName", " ", 1, 3);
g_assert (searches != NULL && searches->next == NULL);
result = searches->data;
g_slist_free_1 (searches);
g_assert (search_result->len == 1);
result = g_strdup ((char *) (search_result->pdata[0]));
g_ptr_array_free (search_result, TRUE);

prod_cleanup:

prod_cleanup:
g_free (cmd_out);
g_free (cmd_err);
g_clear_error (&error);
Expand Down
2 changes: 1 addition & 1 deletion src/utils-platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void cleanup_windows_res (void);
#endif

#if (defined G_OS_WIN32 || defined __GLIBC__)
GSList * enumerate_drive_bins (GError **error);
GPtrArray *enumerate_drive_bins (GError **error);
char * windows_product_name (void);
#endif

Expand Down
24 changes: 17 additions & 7 deletions src/utils-win.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,18 +176,20 @@ _get_user_sid (GError **error)
return NULL;
}

/*
* Probe for logical drives on Windows and return their
* corresponding recycle bin paths for current user

/**
* @brief Probe for possible Windows Recycle Bin paths
* @param error Location to store `GError` when problem arises
* @return List of possible Windows paths in `GPtrArray`
*/
GSList *
GPtrArray *
enumerate_drive_bins (GError **error)
{
DWORD drive_bitmap;
PSID sid = NULL;
char *errmsg = NULL, *sid_str = NULL;
static char drive_root[4] = "A:\\";
GSList *result = NULL;
GPtrArray *result = NULL;

if (NULL == (sid = _get_user_sid (error)))
return NULL;
Expand All @@ -206,6 +208,8 @@ enumerate_drive_bins (GError **error)
goto enumerate_cleanup;
}

result = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);

for (gsize i = 0; i < sizeof(DWORD) * CHAR_BIT; i++)
{
if (! (drive_bitmap & (1 << i)))
Expand All @@ -222,15 +226,21 @@ enumerate_drive_bins (GError **error)
char *full_rbin_path = g_build_filename (drive_root,
"$Recycle.bin", sid_str, NULL);
if (g_file_test (full_rbin_path, G_FILE_TEST_EXISTS))
result = g_slist_prepend (result, full_rbin_path);
g_ptr_array_add (result, full_rbin_path);
else
g_free (full_rbin_path);
}

if (result == NULL)
// Might be possible that even C:\ is network drive
// (e.g. thin client), but still report that as
// error for live mode
if (result->len == 0) {
g_set_error_literal (error, R2_MISC_ERROR,
R2_MISC_ERROR_ENUMERATE_MNT,
_("No recycle bin found on system"));
g_ptr_array_free (result, TRUE);
result = NULL;
}

enumerate_cleanup:

Expand Down
17 changes: 8 additions & 9 deletions src/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,8 @@ _fileargs_handler (GOptionContext *context,
#if (defined G_OS_WIN32 || defined __GLIBC__)
{
meta->filename = g_strdup ("(current system)");
GSList *bindirs = enumerate_drive_bins (error);

GPtrArray *bindirs = enumerate_drive_bins (error);
if (!bindirs)
{
char *reason = g_strdup ((*error)->message);
Expand All @@ -490,15 +491,14 @@ _fileargs_handler (GOptionContext *context,
return FALSE;
}

GSList *ptr = bindirs;
while (ptr) {
for (gsize i = 0; i < bindirs->len; i++)
{
// Ignore errors, pretty common that some folders don't
// exist or are empty.
_check_file_args (ptr->data, allidxfiles,
meta->type, NULL, NULL);
ptr = ptr->next;
_check_file_args ((const char *)(bindirs->pdata[i]),
allidxfiles, meta->type, NULL, NULL);
}
g_slist_free_full (bindirs, g_free);
g_ptr_array_free (bindirs, TRUE);
}
#endif

Expand Down Expand Up @@ -939,8 +939,7 @@ _guess_windows_ver (const metarecord *meta)
/**
* @brief Add potentially valid file(s) to list
* @param path The file or folder to be checked
* @param list A `GSList` pointer to store potential index files
* to be validated later on
* @param list A `GPtrArray` to store potential index files
* @param type Recycle bin type
* @param isolated_index Pointer to `gboolean`, indicating whether
* the concerned `path` is a single `$Recycle.bin` type index
Expand Down

0 comments on commit b2c38db

Please sign in to comment.