[gnome-software/1296-calculate-app-space-usage-for-download-context-tile: 41/43] gs-utils: Introduce gs_utils_get_file_size()




commit 989761f2354b30d7ef416211964170b8bb900211
Author: Milan Crha <mcrha redhat com>
Date:   Thu Jul 29 11:15:45 2021 +0200

    gs-utils: Introduce gs_utils_get_file_size()
    
    A function, which helps to get a file or a directory size.

 lib/gs-utils.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/gs-utils.h | 23 ++++++++++++++++++
 2 files changed, 96 insertions(+)
---
diff --git a/lib/gs-utils.c b/lib/gs-utils.c
index a09a2a00c..99d1ceaec 100644
--- a/lib/gs-utils.c
+++ b/lib/gs-utils.c
@@ -1435,4 +1435,77 @@ gs_utils_pixbuf_blur (GdkPixbuf *src, guint radius, guint iterations)
                gs_pixbuf_blur_private (src, tmp, radius, div_kernel_size);
 }
 
+/**
+ * gs_utils_get_file_size:
+ * @filename: a file name to get the size of; it can be a file or a directory
+ * @include_func: (nullable) (scope call): optional callback to limit what files to count
+ * @user_data: user data passed to the @include_func
+ * @cancellable: (nullable): an optional #GCancellable or %NULL
+ *
+ * Gets the size of the file or a directory identified by @filename.
+ *
+ * When the @include_func is not %NULL, it can limit which files are included
+ * in the resulting size. When it's %NULL, all files and subdirectories are included.
+ *
+ * Returns: disk size of the @filename; or 0 when not found
+ *
+ * Since: 41
+ **/
+guint64
+gs_utils_get_file_size (const gchar *filename,
+                       GsFileSizeIncludeFunc include_func,
+                       gpointer user_data,
+                       GCancellable *cancellable)
+{
+       guint64 size = 0;
+
+       g_return_val_if_fail (filename != NULL, 0);
+
+       if (g_file_test (filename, G_FILE_TEST_IS_DIR)) {
+               GSList *dirs_to_do = NULL;
+               gsize base_len = strlen (filename);
+
+               if (!g_str_has_suffix (filename, G_DIR_SEPARATOR_S))
+                       base_len++;
+
+               dirs_to_do = g_slist_prepend (dirs_to_do, g_strdup (filename));
+               while (dirs_to_do != NULL && !g_cancellable_is_cancelled (cancellable)) {
+                       g_autofree gchar *path = dirs_to_do->data;
+                       g_autoptr(GDir) dir = NULL;
+
+                       dirs_to_do = g_slist_remove (dirs_to_do, path);
+
+                       dir = g_dir_open (path, 0, NULL);
+                       if (dir) {
+                               const gchar *name;
+                               while (name = g_dir_read_name (dir), name != NULL && 
!g_cancellable_is_cancelled (cancellable)) {
+                                       g_autofree gchar *full_path = g_build_filename (path, name, NULL);
+                                       GStatBuf st;
+
+                                       if (g_stat (full_path, &st) == 0 && (include_func == NULL ||
+                                           include_func (full_path + base_len,
+                                                         S_ISLNK (st.st_mode) ? G_FILE_TEST_IS_SYMLINK :
+                                                         S_ISDIR (st.st_mode) ? G_FILE_TEST_IS_DIR :
+                                                         G_FILE_TEST_IS_REGULAR,
+                                                         user_data))) {
+                                               if (S_ISDIR (st.st_mode)) {
+                                                       dirs_to_do = g_slist_prepend (dirs_to_do, 
g_steal_pointer (&full_path));
+                                               } else {
+                                                       size += st.st_size;
+                                               }
+                                       }
+                               }
+                       }
+               }
+               g_slist_free_full (dirs_to_do, g_free);
+       } else {
+               GStatBuf st;
+
+               if (g_stat (filename, &st) == 0)
+                       size = st.st_size;
+       }
+
+       return size;
+}
+
 /* vim: set noexpandtab: */
diff --git a/lib/gs-utils.h b/lib/gs-utils.h
index 2a4402999..66d49bc42 100644
--- a/lib/gs-utils.h
+++ b/lib/gs-utils.h
@@ -106,6 +106,29 @@ void                gs_utils_pixbuf_blur           (GdkPixbuf      *src,
                                                 guint          radius,
                                                 guint          iterations);
 
+/**
+ * GsFileSizeIncludeFunc:
+ * @filename: file name to check
+ * @file_kind: the file kind, one of #GFileTest enums
+ * @user_data: a user data passed to the gs_utils_get_file_size()
+ *
+ * Check whether include the @filename in the size calculation.
+ * The @filename is a relative path to the file name passed to
+ * the #GsFileSizeIncludeFunc.
+ *
+ * Returns: Whether to include the @filename in the size calculation
+ *
+ * Since: 41
+ **/
+typedef gboolean (*GsFileSizeIncludeFunc)      (const gchar            *filename,
+                                                GFileTest               file_kind,
+                                                gpointer                user_data);
+
+guint64                 gs_utils_get_file_size         (const gchar            *filename,
+                                                GsFileSizeIncludeFunc   include_func,
+                                                gpointer                user_data,
+                                                GCancellable           *cancellable);
+
 #if !GLIB_CHECK_VERSION(2, 64, 0)
 typedef void GsMainContextPusher;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]