• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
print_result(const gchar * filename,guint64 disk_usage,guint64 num_dirs,guint64 num_files,GError * error,gchar nl)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 (disk_usage, format_flags);
26           g_print ("%s: %s (%"G_GUINT64_FORMAT" dirs, %"G_GUINT64_FORMAT" files)%c",
27                    filename, str, num_dirs, num_files, nl);
28           g_free (str);
29         }
30       else
31         g_print ("%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 ("%s: %s\n", filename, error->message);
37       g_error_free (error);
38     }
39 }
40 
41 static void
async_ready_func(GObject * source,GAsyncResult * result,gpointer user_data)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, &num_dirs, &num_files, &error);
53   print_result (filename, disk_usage, num_dirs, num_files, error, '\n');
54   outstanding_asyncs--;
55   g_free (filename);
56 }
57 
58 static void
report_progress(gboolean reporting,guint64 disk_usage,guint64 num_dirs,guint64 num_files,gpointer user_data)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 ("%s: warning: does not support progress reporting\n", filename);
69 
70   print_result (filename, disk_usage, num_dirs, num_files, NULL, '\r');
71 }
72 
73 int
main(int argc,char ** argv)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, "");
86 
87 
88 
89   for (i = 1; argv[i] && argv[i][0] == '-'; i++)
90     {
91       if (g_str_equal (argv[i], "--"))
92         break;
93 
94       if (g_str_equal (argv[i], "--help"))
95         {
96           g_print ("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 (argv[i], "-x"))
103         flags |= G_FILE_MEASURE_NO_XDEV;
104       else if (g_str_equal (argv[i], "-h"))
105         option_format_size++;
106       else if (g_str_equal (argv[i], "--apparent-size"))
107         flags |= G_FILE_MEASURE_APPARENT_SIZE;
108       else if (g_str_equal (argv[i], "--any-error"))
109         flags |= G_FILE_MEASURE_REPORT_ANY_ERROR;
110       else if (g_str_equal (argv[i], "--async"))
111         option_use_async = TRUE;
112       else if (g_str_equal (argv[i], "--progress"))
113         progress = report_progress;
114       else
115         {
116           g_printerr ("unrecognised flag %s\n", argv[i]);
117         }
118     }
119 
120   if (!argv[i])
121     {
122       g_printerr ("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 (argv[i]);
132 
133     if (option_use_async)
134     {
135       g_file_measure_disk_usage_async (file, flags, G_PRIORITY_DEFAULT, NULL,
136                                        progress, argv[i], async_ready_func, 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, argv[i],
147                                  &disk_usage, &num_dirs, &num_files, &error);
148       print_result (argv[i], disk_usage, num_dirs, num_files, error, '\n');
149     }
150 
151     g_object_unref (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