1 | #include <gio/gio.h> |
2 | #include <locale.h> |
3 | |
4 | static gboolean option_use_async; |
5 | static gint option_format_size; |
6 | |
7 | static gint outstanding_asyncs; |
8 | |
9 | static void |
10 | print_result (const gchar *filename, |
11 | guint64 disk_usage, |
12 | guint64 num_dirs, |
13 | guint64 num_files, |
14 | GError *error, |
15 | gchar nl) |
16 | { |
17 | if (!error) |
18 | { |
19 | if (option_format_size) |
20 | { |
21 | GFormatSizeFlags format_flags; |
22 | gchar *str; |
23 | |
24 | format_flags = (option_format_size > 1) ? G_FORMAT_SIZE_LONG_FORMAT : G_FORMAT_SIZE_DEFAULT; |
25 | str = g_format_size_full (size: disk_usage, flags: format_flags); |
26 | g_print (format: "%s: %s (%" G_GUINT64_FORMAT" dirs, %" G_GUINT64_FORMAT" files)%c" , |
27 | filename, str, num_dirs, num_files, nl); |
28 | g_free (mem: str); |
29 | } |
30 | else |
31 | g_print (format: "%s: %" G_GUINT64_FORMAT" (%" G_GUINT64_FORMAT" dirs, %" G_GUINT64_FORMAT" files)%c" , |
32 | filename, disk_usage, num_dirs, num_files, nl); |
33 | } |
34 | else |
35 | { |
36 | g_printerr (format: "%s: %s\n" , filename, error->message); |
37 | g_error_free (error); |
38 | } |
39 | } |
40 | |
41 | static void |
42 | async_ready_func (GObject *source, |
43 | GAsyncResult *result, |
44 | gpointer user_data) |
45 | { |
46 | gchar *filename = user_data; |
47 | GError *error = NULL; |
48 | guint64 disk_usage; |
49 | guint64 num_dirs; |
50 | guint64 num_files; |
51 | |
52 | g_file_measure_disk_usage_finish (G_FILE (source), result, disk_usage: &disk_usage, num_dirs: &num_dirs, num_files: &num_files, error: &error); |
53 | print_result (filename, disk_usage, num_dirs, num_files, error, nl: '\n'); |
54 | outstanding_asyncs--; |
55 | g_free (mem: filename); |
56 | } |
57 | |
58 | static void |
59 | report_progress (gboolean reporting, |
60 | guint64 disk_usage, |
61 | guint64 num_dirs, |
62 | guint64 num_files, |
63 | gpointer user_data) |
64 | { |
65 | const gchar *filename = user_data; |
66 | |
67 | if (!reporting) |
68 | g_printerr (format: "%s: warning: does not support progress reporting\n" , filename); |
69 | |
70 | print_result (filename, disk_usage, num_dirs, num_files, NULL, nl: '\r'); |
71 | } |
72 | |
73 | int |
74 | main (int argc, char **argv) |
75 | { |
76 | GFileMeasureProgressCallback progress = NULL; |
77 | GFileMeasureFlags flags = 0; |
78 | gint i; |
79 | |
80 | #ifdef G_OS_WIN32 |
81 | argv = g_win32_get_command_line (); |
82 | argc = g_strv_length (argv); |
83 | #endif |
84 | |
85 | setlocale (LC_ALL, locale: "" ); |
86 | |
87 | |
88 | |
89 | for (i = 1; argv[i] && argv[i][0] == '-'; i++) |
90 | { |
91 | if (g_str_equal (v1: argv[i], v2: "--" )) |
92 | break; |
93 | |
94 | if (g_str_equal (v1: argv[i], v2: "--help" )) |
95 | { |
96 | g_print (format: "usage: du [--progress] [--async] [-x] [-h] [-h] [--apparent-size] [--any-error] [--] files...\n" ); |
97 | #ifdef G_OS_WIN32 |
98 | g_strfreev (argv); |
99 | #endif |
100 | return 0; |
101 | } |
102 | else if (g_str_equal (v1: argv[i], v2: "-x" )) |
103 | flags |= G_FILE_MEASURE_NO_XDEV; |
104 | else if (g_str_equal (v1: argv[i], v2: "-h" )) |
105 | option_format_size++; |
106 | else if (g_str_equal (v1: argv[i], v2: "--apparent-size" )) |
107 | flags |= G_FILE_MEASURE_APPARENT_SIZE; |
108 | else if (g_str_equal (v1: argv[i], v2: "--any-error" )) |
109 | flags |= G_FILE_MEASURE_REPORT_ANY_ERROR; |
110 | else if (g_str_equal (v1: argv[i], v2: "--async" )) |
111 | option_use_async = TRUE; |
112 | else if (g_str_equal (v1: argv[i], v2: "--progress" )) |
113 | progress = report_progress; |
114 | else |
115 | { |
116 | g_printerr (format: "unrecognised flag %s\n" , argv[i]); |
117 | } |
118 | } |
119 | |
120 | if (!argv[i]) |
121 | { |
122 | g_printerr (format: "usage: du [--progress] [--async] [-x] [-h] [-h] [--apparent-size] [--any-error] [--] files...\n" ); |
123 | #ifdef G_OS_WIN32 |
124 | g_strfreev (argv); |
125 | #endif |
126 | return 1; |
127 | } |
128 | |
129 | while (argv[i]) |
130 | { |
131 | GFile *file = g_file_new_for_commandline_arg (arg: argv[i]); |
132 | |
133 | if (option_use_async) |
134 | { |
135 | g_file_measure_disk_usage_async (file, flags, G_PRIORITY_DEFAULT, NULL, |
136 | progress_callback: progress, progress_data: argv[i], callback: async_ready_func, user_data: argv[i]); |
137 | outstanding_asyncs++; |
138 | } |
139 | else |
140 | { |
141 | GError *error = NULL; |
142 | guint64 disk_usage; |
143 | guint64 num_dirs; |
144 | guint64 num_files; |
145 | |
146 | g_file_measure_disk_usage (file, flags, NULL, progress_callback: progress, progress_data: argv[i], |
147 | disk_usage: &disk_usage, num_dirs: &num_dirs, num_files: &num_files, error: &error); |
148 | print_result (filename: argv[i], disk_usage, num_dirs, num_files, error, nl: '\n'); |
149 | } |
150 | |
151 | g_object_unref (object: file); |
152 | |
153 | i++; |
154 | } |
155 | |
156 | while (outstanding_asyncs) |
157 | g_main_context_iteration (NULL, TRUE); |
158 | |
159 | #ifdef G_OS_WIN32 |
160 | g_strfreev (argv); |
161 | #endif |
162 | |
163 | return 0; |
164 | } |
165 | |