summaryrefslogtreecommitdiff
path: root/libcaja-private/caja-file.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcaja-private/caja-file.c')
-rw-r--r--libcaja-private/caja-file.c203
1 files changed, 165 insertions, 38 deletions
diff --git a/libcaja-private/caja-file.c b/libcaja-private/caja-file.c
index 2ea025e4..769ca822 100644
--- a/libcaja-private/caja-file.c
+++ b/libcaja-private/caja-file.c
@@ -119,6 +119,7 @@ static GHashTable *symbolic_links;
static GQuark attribute_name_q,
attribute_size_q,
+ attribute_size_on_disk_q,
attribute_type_q,
attribute_modification_date_q,
attribute_date_modified_q,
@@ -127,7 +128,9 @@ static GQuark attribute_name_q,
attribute_emblems_q,
attribute_mime_type_q,
attribute_size_detail_q,
+ attribute_size_on_disk_detail_q,
attribute_deep_size_q,
+ attribute_deep_size_on_disk_q,
attribute_deep_file_count_q,
attribute_deep_directory_count_q,
attribute_deep_total_count_q,
@@ -466,6 +469,7 @@ caja_file_clear_info (CajaFile *file)
file->details->has_permissions = FALSE;
file->details->permissions = 0;
file->details->size = -1;
+ file->details->size_on_disk = -1;
file->details->sort_order = 0;
file->details->mtime = 0;
file->details->atime = 0;
@@ -2094,6 +2098,7 @@ update_info_internal (CajaFile *file,
gboolean thumbnailing_failed;
int uid, gid;
goffset size;
+ goffset size_on_disk;
int sort_order;
time_t atime, mtime, ctime;
time_t trash_time;
@@ -2369,6 +2374,15 @@ update_info_internal (CajaFile *file,
}
file->details->size = size;
+ size_on_disk = -1;
+ if (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE)) {
+ size_on_disk = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE);
+ }
+ if (file->details->size_on_disk != size_on_disk) {
+ changed = TRUE;
+ }
+ file->details->size_on_disk = size_on_disk;
+
sort_order = g_file_info_get_sort_order (info);
if (file->details->sort_order != sort_order) {
changed = TRUE;
@@ -2662,7 +2676,8 @@ get_item_count (CajaFile *file,
static Knowledge
get_size (CajaFile *file,
- goffset *size)
+ goffset *size,
+ gboolean size_on_disk)
{
/* If we tried and failed, then treat it like there is no size
* to know.
@@ -2682,12 +2697,21 @@ get_size (CajaFile *file,
* such thing as a size as far as mate-vfs is concerned,
* so "unknowable".
*/
- if (file->details->size == -1) {
+ if (size_on_disk && file->details->size_on_disk == -1) {
+ return UNKNOWABLE;
+ }
+
+ if (!size_on_disk && file->details->size == -1) {
return UNKNOWABLE;
}
/* We have a size! */
- *size = file->details->size;
+ if (size_on_disk) {
+ *size = file->details->size_on_disk;
+ } else {
+ *size = file->details->size;
+ }
+
return KNOWN;
}
@@ -2781,7 +2805,7 @@ compare_directories_by_count (CajaFile *file_1, CajaFile *file_2)
}
static int
-compare_files_by_size (CajaFile *file_1, CajaFile *file_2)
+compare_files_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
{
/* Sort order:
* Files with unknown size.
@@ -2793,8 +2817,8 @@ compare_files_by_size (CajaFile *file_1, CajaFile *file_2)
Knowledge size_known_1, size_known_2;
goffset size_1 = 0, size_2 = 0;
- size_known_1 = get_size (file_1, &size_1);
- size_known_2 = get_size (file_2, &size_2);
+ size_known_1 = get_size (file_1, &size_1, size_on_disk);
+ size_known_2 = get_size (file_2, &size_2, size_on_disk);
if (size_known_1 > size_known_2) {
return -1;
@@ -2821,7 +2845,7 @@ compare_files_by_size (CajaFile *file_1, CajaFile *file_2)
}
static int
-compare_by_size (CajaFile *file_1, CajaFile *file_2)
+compare_by_size (CajaFile *file_1, CajaFile *file_2, gboolean size_on_disk)
{
/* Sort order:
* Directories with n items
@@ -2849,7 +2873,7 @@ compare_by_size (CajaFile *file_1, CajaFile *file_2)
if (is_directory_1) {
return compare_directories_by_count (file_1, file_2);
} else {
- return compare_files_by_size (file_1, file_2);
+ return compare_files_by_size (file_1, file_2, size_on_disk);
}
}
@@ -3211,7 +3235,16 @@ caja_file_compare_for_sort (CajaFile *file_1,
/* Compare directory sizes ourselves, then if necessary
* use MateVFS to compare file sizes.
*/
- result = compare_by_size (file_1, file_2);
+ result = compare_by_size (file_1, file_2, FALSE);
+ if (result == 0) {
+ result = compare_by_full_path (file_1, file_2);
+ }
+ break;
+ case CAJA_FILE_SORT_BY_SIZE_ON_DISK:
+ /* Compare directory sizes ourselves, then if necessary
+ * use MateVFS to compare file sizes.
+ */
+ result = compare_by_size (file_1, file_2, TRUE);
if (result == 0) {
result = compare_by_full_path (file_1, file_2);
}
@@ -3291,6 +3324,11 @@ caja_file_compare_for_sort_by_attribute_q (CajaFile *file_1,
CAJA_FILE_SORT_BY_SIZE,
directories_first,
reversed);
+ } else if (attribute == attribute_size_on_disk_q) {
+ return caja_file_compare_for_sort (file_1, file_2,
+ CAJA_FILE_SORT_BY_SIZE_ON_DISK,
+ directories_first,
+ reversed);
} else if (attribute == attribute_type_q) {
return caja_file_compare_for_sort (file_1, file_2,
CAJA_FILE_SORT_BY_TYPE,
@@ -4877,6 +4915,7 @@ caja_file_get_directory_item_count (CajaFile *file,
* @unreadable_directory_count: Number of directories encountered
* that were unreadable.
* @total_size: Total size of all files and directories visited.
+ * @total_size_on_disk: Total size on disk of all files and directories visited.
* @force: Whether the deep counts should even be collected if
* caja_file_should_show_directory_item_count returns FALSE
* for this file.
@@ -4890,6 +4929,7 @@ caja_file_get_deep_counts (CajaFile *file,
guint *file_count,
guint *unreadable_directory_count,
goffset *total_size,
+ goffset *total_size_on_disk,
gboolean force)
{
if (directory_count != NULL) {
@@ -4904,6 +4944,9 @@ caja_file_get_deep_counts (CajaFile *file,
if (total_size != NULL) {
*total_size = 0;
}
+ if (total_size_on_disk != NULL) {
+ *total_size_on_disk = 0;
+ }
g_return_val_if_fail (CAJA_IS_FILE (file), CAJA_REQUEST_DONE);
@@ -4921,7 +4964,8 @@ caja_file_get_deep_counts (CajaFile *file,
directory_count,
file_count,
unreadable_directory_count,
- total_size));
+ total_size,
+ total_size_on_disk));
}
void
@@ -4961,6 +5005,27 @@ caja_file_get_size (CajaFile *file)
return file->details->size;
}
+/**
+ * caja_file_get_size_on_disk
+ *
+ * Get the file size on disk (how many bytes is using on the filesystem).
+ * e.g.: usually files with 1 byte will use a whole inode so it will return the
+ * size of 1 inode. If the file is sparse the size on disk will be equal or less
+ * than the size of the file.
+ * @file: CajaFile representing the file in question.
+ *
+ * Returns: Size in bytes.
+ *
+ **/
+goffset
+caja_file_get_size_on_disk (CajaFile *file)
+{
+ /* Before we have info on the file, we don't know the size. */
+ if (file->details->size_on_disk == -1)
+ return 0;
+ return file->details->size_on_disk;
+}
+
time_t
caja_file_get_mtime (CajaFile *file)
{
@@ -5894,15 +5959,18 @@ format_item_count_for_display (guint item_count,
* is responsible for g_free-ing this string. The string is an item
* count for directories.
* @file: CajaFile representing the file in question.
+ * @size_on_disk: If TRUE will return the size on disk. If FALSE return file size.
*
* Returns: Newly allocated string ready to display to the user.
*
**/
static char *
-caja_file_get_size_as_string (CajaFile *file)
+caja_file_get_size_as_string (CajaFile *file,
+ gboolean size_on_disk)
{
guint item_count;
gboolean count_unreadable;
+ goffset size;
if (file == NULL) {
return NULL;
@@ -5917,14 +5985,20 @@ caja_file_get_size_as_string (CajaFile *file)
return format_item_count_for_display (item_count, TRUE, TRUE);
}
- if (file->details->size == -1) {
+ if (size_on_disk) {
+ size = file->details->size_on_disk;
+ } else {
+ size = file->details->size;
+ }
+
+ if (size == -1) {
return NULL;
}
if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS))
- return g_format_size_full (file->details->size, G_FORMAT_SIZE_IEC_UNITS);
+ return g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
else
- return g_format_size (file->details->size);
+ return g_format_size (size);
}
/**
@@ -5940,10 +6014,12 @@ caja_file_get_size_as_string (CajaFile *file)
*
**/
static char *
-caja_file_get_size_as_string_with_real_size (CajaFile *file)
+caja_file_get_size_as_string_with_real_size (CajaFile *file,
+ gboolean size_on_disk)
{
guint item_count;
gboolean count_unreadable;
+ goffset size;
char * formatted;
char * formatted_plus_real;
char * real_size;
@@ -5961,27 +6037,33 @@ caja_file_get_size_as_string_with_real_size (CajaFile *file)
return format_item_count_for_display (item_count, TRUE, TRUE);
}
- if (file->details->size == -1) {
+ if (size_on_disk) {
+ size = file->details->size_on_disk;
+ } else {
+ size = file->details->size;
+ }
+
+ if (size == -1) {
return NULL;
}
if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS))
- formatted = g_format_size_full (file->details->size, G_FORMAT_SIZE_IEC_UNITS);
+ formatted = g_format_size_full (size, G_FORMAT_SIZE_IEC_UNITS);
else
- formatted = g_format_size(file->details->size);
+ formatted = g_format_size(size);
/* Do this in a separate stage so that we don't have to put G_GUINT64_FORMAT in the translated string */
- real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT), (guint64) file->details->size);
+ real_size = g_strdup_printf (_("%"G_GUINT64_FORMAT), (guint64) size);
formatted_plus_real = g_strdup_printf (_("%s (%s bytes)"), formatted, real_size);
g_free (real_size);
g_free (formatted);
return formatted_plus_real;
}
-
static char *
caja_file_get_deep_count_as_string_internal (CajaFile *file,
gboolean report_size,
+ gboolean report_size_on_disk,
gboolean report_directory_count,
gboolean report_file_count)
{
@@ -5991,10 +6073,15 @@ caja_file_get_deep_count_as_string_internal (CajaFile *file,
guint unreadable_count;
guint total_count;
goffset total_size;
+ goffset total_size_on_disk;
+
+ /* Can't ask for more than one of those: size, size on disk or (directory and/or file count) */
+ g_assert (!(report_size && report_size_on_disk));
+ g_assert (!(report_size && (report_directory_count || report_file_count)));
+ g_assert (!(report_size_on_disk && (report_directory_count || report_file_count)));
- /* Must ask for size or some kind of count, but not both. */
- g_assert (!report_size || (!report_directory_count && !report_file_count));
- g_assert (report_size || report_directory_count || report_file_count);
+ /* Must ask for something */
+ g_assert (report_size || report_size_on_disk || report_directory_count || report_file_count);
if (file == NULL) {
return NULL;
@@ -6003,8 +6090,13 @@ caja_file_get_deep_count_as_string_internal (CajaFile *file,
g_assert (CAJA_IS_FILE (file));
g_assert (caja_file_is_directory (file));
- status = caja_file_get_deep_counts
- (file, &directory_count, &file_count, &unreadable_count, &total_size, FALSE);
+ status = caja_file_get_deep_counts (file,
+ &directory_count,
+ &file_count,
+ &unreadable_count,
+ &total_size,
+ &total_size_on_disk,
+ FALSE);
/* Check whether any info is available. */
if (status == CAJA_REQUEST_NOT_STARTED) {
@@ -6042,6 +6134,14 @@ caja_file_get_deep_count_as_string_internal (CajaFile *file,
return g_format_size(total_size);
}
+ if (report_size_on_disk)
+ {
+ if (g_settings_get_boolean (caja_preferences, CAJA_PREFERENCES_USE_IEC_UNITS))
+ return g_format_size_full (total_size_on_disk, G_FORMAT_SIZE_IEC_UNITS);
+ else
+ return g_format_size (total_size_on_disk);
+ }
+
return format_item_count_for_display (report_directory_count
? (report_file_count ? total_count : directory_count)
: file_count,
@@ -6055,14 +6155,19 @@ caja_file_get_deep_count_as_string_internal (CajaFile *file,
* items (only makes sense for directories). The caller
* is responsible for g_free-ing this string.
* @file: CajaFile representing the file in question.
+ * @size_on_disk: if TRUE will return the size on disk, else return size of file.
*
* Returns: Newly allocated string ready to display to the user.
*
**/
static char *
-caja_file_get_deep_size_as_string (CajaFile *file)
+caja_file_get_deep_size_as_string (CajaFile *file, gboolean size_on_disk)
{
- return caja_file_get_deep_count_as_string_internal (file, TRUE, FALSE, FALSE);
+ if (size_on_disk) {
+ return caja_file_get_deep_count_as_string_internal (file, FALSE, TRUE, FALSE, FALSE);
+ } else {
+ return caja_file_get_deep_count_as_string_internal (file, TRUE, FALSE, FALSE, FALSE);
+ }
}
/**
@@ -6079,7 +6184,7 @@ caja_file_get_deep_size_as_string (CajaFile *file)
static char *
caja_file_get_deep_total_count_as_string (CajaFile *file)
{
- return caja_file_get_deep_count_as_string_internal (file, FALSE, TRUE, TRUE);
+ return caja_file_get_deep_count_as_string_internal (file, FALSE, FALSE, TRUE, TRUE);
}
/**
@@ -6097,7 +6202,7 @@ caja_file_get_deep_total_count_as_string (CajaFile *file)
static char *
caja_file_get_deep_file_count_as_string (CajaFile *file)
{
- return caja_file_get_deep_count_as_string_internal (file, FALSE, FALSE, TRUE);
+ return caja_file_get_deep_count_as_string_internal (file, FALSE, FALSE, FALSE, TRUE);
}
/**
@@ -6115,7 +6220,7 @@ caja_file_get_deep_file_count_as_string (CajaFile *file)
static char *
caja_file_get_deep_directory_count_as_string (CajaFile *file)
{
- return caja_file_get_deep_count_as_string_internal (file, FALSE, TRUE, FALSE);
+ return caja_file_get_deep_count_as_string_internal (file, FALSE, FALSE, TRUE, FALSE);
}
/**
@@ -6128,9 +6233,9 @@ caja_file_get_deep_directory_count_as_string (CajaFile *file)
*
* @file: CajaFile representing the file in question.
* @attribute_name: The name of the desired attribute. The currently supported
- * set includes "name", "type", "mime_type", "size", "deep_size", "deep_directory_count",
- * "deep_file_count", "deep_total_count", "date_modified", "date_changed", "date_accessed",
- * "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
+ * set includes "name", "type", "mime_type", "size", "size_on_disk", "deep_size", "deep_size_on_disk",
+ * "deep_directory_count", "deep_file_count", "deep_total_count", "date_modified", "date_changed",
+ * "date_accessed", "date_permissions", "owner", "group", "permissions", "octal_permissions", "uri", "where",
* "link_target", "volume", "free_space", "selinux_context", "trashed_on", "trashed_orig_path"
*
* Returns: Newly allocated string ready to display to the user, or NULL
@@ -6152,13 +6257,22 @@ caja_file_get_string_attribute_q (CajaFile *file, GQuark attribute_q)
return caja_file_get_mime_type (file);
}
if (attribute_q == attribute_size_q) {
- return caja_file_get_size_as_string (file);
+ return caja_file_get_size_as_string (file, FALSE);
+ }
+ if (attribute_q == attribute_size_on_disk_q) {
+ return caja_file_get_size_as_string (file, TRUE);
}
if (attribute_q == attribute_size_detail_q) {
- return caja_file_get_size_as_string_with_real_size (file);
+ return caja_file_get_size_as_string_with_real_size (file, FALSE);
+ }
+ if (attribute_q == attribute_size_on_disk_detail_q) {
+ return caja_file_get_size_as_string_with_real_size (file, TRUE);
}
if (attribute_q == attribute_deep_size_q) {
- return caja_file_get_deep_size_as_string (file);
+ return caja_file_get_deep_size_as_string (file, FALSE);
+ }
+ if (attribute_q == attribute_deep_size_on_disk_q) {
+ return caja_file_get_deep_size_as_string (file, TRUE);
}
if (attribute_q == attribute_deep_file_count_q) {
return caja_file_get_deep_file_count_as_string (file);
@@ -6290,7 +6404,15 @@ caja_file_get_string_attribute_with_default_q (CajaFile *file, GQuark attribute_
return g_strdup (count_unreadable ? _("? items") : "...");
}
if (attribute_q == attribute_deep_size_q) {
- status = caja_file_get_deep_counts (file, NULL, NULL, NULL, NULL, FALSE);
+ status = caja_file_get_deep_counts (file, NULL, NULL, NULL, NULL, NULL, FALSE);
+ if (status == CAJA_REQUEST_DONE) {
+ /* This means no contents at all were readable */
+ return g_strdup (_("? bytes"));
+ }
+ return g_strdup ("...");
+ }
+ if (attribute_q == attribute_deep_size_on_disk_q) {
+ status = caja_file_get_deep_counts (file, NULL, NULL, NULL, NULL, NULL, FALSE);
if (status == CAJA_REQUEST_DONE) {
/* This means no contents at all were readable */
return g_strdup (_("? bytes"));
@@ -6300,7 +6422,7 @@ caja_file_get_string_attribute_with_default_q (CajaFile *file, GQuark attribute_
if (attribute_q == attribute_deep_file_count_q
|| attribute_q == attribute_deep_directory_count_q
|| attribute_q == attribute_deep_total_count_q) {
- status = caja_file_get_deep_counts (file, NULL, NULL, NULL, NULL, FALSE);
+ status = caja_file_get_deep_counts (file, NULL, NULL, NULL, NULL, NULL, FALSE);
if (status == CAJA_REQUEST_DONE) {
/* This means no contents at all were readable */
return g_strdup (_("? items"));
@@ -7688,6 +7810,7 @@ void
caja_file_dump (CajaFile *file)
{
long size = file->details->deep_size;
+ long size_on_disk = file->details->deep_size_on_disk;
char *uri;
const char *file_kind;
@@ -7699,6 +7822,7 @@ caja_file_dump (CajaFile *file)
g_print ("failed to get file info \n");
} else {
g_print ("size: %ld \n", size);
+ g_print ("disk size: %ld \n", size_on_disk);
switch (file->details->type) {
case G_FILE_TYPE_REGULAR:
file_kind = "regular file";
@@ -8199,6 +8323,7 @@ caja_file_class_init (CajaFileClass *class)
attribute_name_q = g_quark_from_static_string ("name");
attribute_size_q = g_quark_from_static_string ("size");
+ attribute_size_on_disk_q = g_quark_from_static_string ("size_on_disk");
attribute_type_q = g_quark_from_static_string ("type");
attribute_modification_date_q = g_quark_from_static_string ("modification_date");
attribute_date_modified_q = g_quark_from_static_string ("date_modified");
@@ -8207,7 +8332,9 @@ caja_file_class_init (CajaFileClass *class)
attribute_emblems_q = g_quark_from_static_string ("emblems");
attribute_mime_type_q = g_quark_from_static_string ("mime_type");
attribute_size_detail_q = g_quark_from_static_string ("size_detail");
+ attribute_size_on_disk_detail_q = g_quark_from_static_string ("size_on_disk_detail");
attribute_deep_size_q = g_quark_from_static_string ("deep_size");
+ attribute_deep_size_on_disk_q = g_quark_from_static_string ("deep_size_on_disk");
attribute_deep_file_count_q = g_quark_from_static_string ("deep_file_count");
attribute_deep_directory_count_q = g_quark_from_static_string ("deep_directory_count");
attribute_deep_total_count_q = g_quark_from_static_string ("deep_total_count");