1 /**
2 * This file is a part of the Cairo-Dock project
3 *
4 * Copyright : (C) see the 'copyright' file.
5 * E-mail : see the 'copyright' file.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <string.h>
21 #include <sys/types.h>
22 #if defined(__FreeBSD__) || defined(__DragonFly__)
23 #include <sys/param.h>
24 #include <sys/ucred.h>
25 #include <sys/mount.h>
26 #else
27 #include <mntent.h>
28 #include <sys/statfs.h>
29 #endif
30
31 #include <math.h>
32
33 #include <cairo-dock.h>
34
35 #include "applet-struct.h"
36 #include "applet-disk-usage.h"
37
38
cd_shortcuts_get_fs_stat(const gchar * cDiskURI,CDDiskUsage * pDiskUsage)39 void cd_shortcuts_get_fs_stat (const gchar *cDiskURI, CDDiskUsage *pDiskUsage)
40 {
41 static struct statfs sts;
42 const gchar *cMountPath = (strncmp (cDiskURI, "file://", 7) == 0 ? cDiskURI + 7 : cDiskURI);
43
44 if (statfs (cMountPath, &sts) == 0)
45 {
46 if (pDiskUsage->iType == 0)
47 pDiskUsage->iType = sts.f_type;
48 pDiskUsage->iAvail = (long long)sts.f_bavail * sts.f_bsize; // Blocs libres pour utilisateurs
49 pDiskUsage->iFree = (long long)sts.f_bfree * sts.f_bsize; // Blocs libres
50 pDiskUsage->iTotal = (long long)sts.f_blocks * sts.f_bsize; // Nombre total de blocs
51 pDiskUsage->iUsed = pDiskUsage->iTotal - pDiskUsage->iAvail;
52 //g_print ("%lld / %lld\n", pDiskUsage->iAvail, pDiskUsage->iTotal);
53 }
54 else
55 {
56 pDiskUsage->iTotal = 0;
57 pDiskUsage->iAvail = 0;
58 }
59 }
60
_display_disk_usage(Icon * pIcon,GldiContainer * pContainer,CDDiskUsage * pDiskUsage,GldiModuleInstance * myApplet)61 static void _display_disk_usage (Icon *pIcon, GldiContainer *pContainer, CDDiskUsage *pDiskUsage, GldiModuleInstance *myApplet)
62 {
63 double fValue;
64 if (pDiskUsage->iTotal != 0 && (pDiskUsage->iPrevAvail == -1 || (double)fabs (pDiskUsage->iPrevAvail - pDiskUsage->iAvail) / pDiskUsage->iTotal > .001)) // .1 % d'ecart ou info encore non renseignee.
65 {
66 pDiskUsage->iPrevAvail = pDiskUsage->iAvail;
67 switch (myConfig.iDisplayType)
68 {
69 case CD_SHOW_FREE_SPACE :
70 fValue = (double) pDiskUsage->iAvail / pDiskUsage->iTotal;
71 cairo_dock_set_size_as_quick_info (pIcon, pDiskUsage->iAvail);
72 break ;
73 case CD_SHOW_USED_SPACE :
74 fValue = (double) pDiskUsage->iUsed / pDiskUsage->iTotal;
75 cairo_dock_set_size_as_quick_info (pIcon, pDiskUsage->iUsed);
76 break ;
77 case CD_SHOW_FREE_SPACE_PERCENT :
78 fValue = (double) pDiskUsage->iAvail / pDiskUsage->iTotal;
79 gldi_icon_set_quick_info_printf (pIcon, "%.1f%%", 100.*fValue);
80 break ;
81 case CD_SHOW_USED_SPACE_PERCENT :
82 fValue = (double) pDiskUsage->iUsed / pDiskUsage->iTotal;
83 gldi_icon_set_quick_info_printf (pIcon, "%.1f%%", 100.*fValue);
84 break ;
85 default:
86 fValue = CAIRO_DATA_RENDERER_UNDEF_VALUE;
87 break;
88 }
89
90 if (myConfig.bDrawBar)
91 cairo_dock_render_new_data_on_icon (pIcon, pContainer, myDrawContext, &fValue);
92 else // just trigger the redraw for the quick-info
93 cairo_dock_redraw_icon (pIcon);
94 }
95 }
96
cd_shortcuts_display_disk_usage(Icon * pIcon,GldiModuleInstance * myApplet)97 void cd_shortcuts_display_disk_usage (Icon *pIcon, GldiModuleInstance *myApplet)
98 {
99 GldiContainer *pContainer = pIcon->pContainer;
100 g_return_if_fail (pContainer != NULL);
101 CDDiskUsage *pDiskUsage = CD_APPLET_GET_MY_ICON_DATA (pIcon);
102 g_return_if_fail (pDiskUsage != NULL);
103 _display_disk_usage (pIcon, pContainer, pDiskUsage, myApplet);
104 }
105
_cd_shortcuts_update_disk_usage(GldiModuleInstance * myApplet)106 static gboolean _cd_shortcuts_update_disk_usage (GldiModuleInstance *myApplet)
107 {
108 CD_APPLET_ENTER;
109 GldiContainer *pContainer = CD_APPLET_MY_ICONS_LIST_CONTAINER;
110 CDDiskUsage *pDiskUsage;
111 Icon *pIcon;
112 GList *ic;
113 GList *pIconsList = CD_APPLET_MY_ICONS_LIST;
114 for (ic = pIconsList; ic != NULL; ic = ic->next)
115 {
116 pIcon = ic->data;
117 if (pIcon->cCommand != NULL) // skip separators
118 {
119 // get data
120 pDiskUsage = CD_APPLET_GET_MY_ICON_DATA (pIcon);
121 if (pDiskUsage == NULL) // not a drive (eg, network or bookmark)
122 {
123 /* Drives are listed first, and Home is always the first
124 * bookmark (and the only one to have disk data), so if we got a
125 * bookmark with no disk data, we can quit the loop.
126 */
127 if (pIcon->iGroup >= (CairoDockIconGroup) CD_BOOKMARK_GROUP)
128 break;
129 else
130 continue;
131 }
132 cd_shortcuts_get_fs_stat (pIcon->cCommand, pDiskUsage);
133
134 // draw
135 _display_disk_usage (pIcon, pContainer, pDiskUsage, myApplet);
136 }
137 }
138
139 if (myDesklet)
140 cairo_dock_redraw_container (myContainer);
141
142 CD_APPLET_LEAVE (TRUE);
143 }
144
145
cd_shortcuts_launch_disk_periodic_task(GldiModuleInstance * myApplet)146 void cd_shortcuts_launch_disk_periodic_task (GldiModuleInstance *myApplet)
147 {
148 if (myConfig.iDisplayType != CD_SHOW_NOTHING && myConfig.bListDrives)
149 {
150 if (myData.pDiskTask == NULL)
151 {
152 myData.pDiskTask = gldi_task_new (myConfig.iCheckInterval,
153 (GldiGetDataAsyncFunc) NULL,
154 (GldiUpdateSyncFunc) _cd_shortcuts_update_disk_usage,
155 myApplet);
156 }
157 gldi_task_launch (myData.pDiskTask);
158 }
159 }
160
cd_shortcuts_free_disk_periodic_task(GldiModuleInstance * myApplet)161 void cd_shortcuts_free_disk_periodic_task (GldiModuleInstance *myApplet)
162 {
163 gldi_task_free (myData.pDiskTask);
164 myData.pDiskTask = NULL;
165 }
166
167
168
_cd_shortcuts_get_fs_info(const gchar * cDiskURI,GString * sInfo)169 static void _cd_shortcuts_get_fs_info (const gchar *cDiskURI, GString *sInfo)
170 {
171 const gchar *cMountPath = (strncmp (cDiskURI, "file://", 7) == 0 ? cDiskURI + 7 : cDiskURI);
172
173 #if defined(__FreeBSD__) || defined(__DragonFly__)
174 struct statfs *me;
175 int i, count = getfsstat(me, NULL, MNT_WAIT);
176 if (count>0)
177 {
178 for (i=0; i<count; i++)
179 {
180 if (me->f_mntonname && strcmp (me->f_mntonname, cMountPath) == 0)
181 {
182 g_string_append_printf (sInfo, "%s %s\n%s %s\n%s %s\n%s %s",
183 D_("Mount point:"), me->f_mntonname,
184 D_("File system:"), me->f_mntfromname,
185 D_("Device:"), me->f_fstypename,
186 #ifdef __DragonFly__
187 D_("Mount options:"), "N/I");
188 #else
189 D_("Mount options:"), me->f_charspare);
190 #endif
191 // if (me->mnt_freq != 0)
192 // g_string_append_printf (sInfo, "\nBackup frequency : %d days", me->mnt_freq);
193 break ;
194 }
195 }
196 }
197 else
198 {
199 cd_warning ("error getfsstat...");
200 return ;
201 }
202 #else
203 struct mntent *me;
204 FILE *mtab = setmntent ("/etc/mtab", "r");
205 if (mtab == NULL)
206 {
207 cd_warning ("couldn't open /etc/mtab");
208 return ;
209 }
210
211 while ((me = getmntent (mtab)) != NULL)
212 {
213 if (me->mnt_dir && strcmp (me->mnt_dir, cMountPath) == 0)
214 {
215 g_string_append_printf (sInfo, "%s %s\n%s %s\n%s %s\n%s %s",
216 D_("Mount point:"), me->mnt_dir,
217 D_("File system:"), me->mnt_type,
218 D_("Device:"), me->mnt_fsname,
219 D_("Mount options:"), me->mnt_opts);
220 if (me->mnt_freq != 0)
221 g_string_append_printf (sInfo, "\n%s %d %s",
222 D_("Backup frequency:"), me->mnt_freq, D_("days"));
223 break ;
224 }
225 }
226
227 endmntent (mtab);
228 #endif
229 }
230
cd_shortcuts_get_disk_info(const gchar * cDiskURI,const gchar * cDiskName)231 gchar *cd_shortcuts_get_disk_info (const gchar *cDiskURI, const gchar *cDiskName)
232 {
233 GString *sInfo = g_string_new ("");
234 // on recupere les infos de taille.
235 CDDiskUsage diskUsage;
236 memset (&diskUsage, 0, sizeof (CDDiskUsage));
237 cd_shortcuts_get_fs_stat (cDiskURI, &diskUsage);
238
239 // on recupere les infos du file system.
240 if (diskUsage.iTotal > 0) // info are available
241 {
242 gchar *cFreeSpace = cairo_dock_get_human_readable_size (diskUsage.iAvail);
243 gchar *cCapacity = cairo_dock_get_human_readable_size (diskUsage.iTotal);
244 g_string_append_printf (sInfo, "%s %s\n%s %s\n%s %s\n", // added '\n' -> _cd_shortcuts_get_fs_info
245 D_("Name:"), cDiskName,
246 D_("Capacity:"), cCapacity,
247 D_("Free space:"), cFreeSpace);
248 g_free (cCapacity);
249 g_free (cFreeSpace);
250 _cd_shortcuts_get_fs_info (cDiskURI, sInfo);
251 }
252 else if (strncmp (cDiskURI, "computer:/", 10) == 0 || strncmp (cDiskURI, "file:/", 6) == 0) // no info on a local mount point => it's not mounted
253 {
254 g_string_append_printf (sInfo, "%s %s\n%s",
255 D_("Name:"), cDiskName, D_("Not mounted"));
256 }
257 else // not a local mount point => a distant connection
258 {
259 g_string_append_printf (sInfo, "%s %s\n%s %s",
260 D_("Name:"), cDiskName,
261 D_("URL:"), cDiskURI);
262 }
263
264 gchar *cInfo = sInfo->str;
265 g_string_free (sInfo, FALSE);
266 return cInfo;
267 }
268