Imported Upstream version 1.2.0
[psensor-pkg-debian.git] / src / lib / pudisks2.c
1 /*
2  * Copyright (C) 2010-2016 jeanfi@gmail.com
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301 USA
18  */
19 #include <locale.h>
20 #include <libintl.h>
21 #define _(str) gettext(str)
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/time.h>
26
27 #include <udisks/udisks.h>
28
29 #include <pudisks2.h>
30 #include <temperature.h>
31
32 static const char *PROVIDER_NAME = "udisks2";
33
34 static GDBusObjectManager *manager;
35
36 static const time_t SMART_UPDATE_INTERVAL = 30;
37
38 struct udisks_data {
39         char *path;
40         struct timeval last_smart_update;
41 };
42
43 static void udisks_data_free(void *data)
44 {
45         struct udisks_data *u;
46
47         u = (struct udisks_data *)data;
48         free(u->path);
49         free(u);
50 }
51
52 static void smart_update(struct psensor *s, UDisksDriveAta *ata)
53 {
54         GVariant *variant;
55         gboolean ret;
56         struct timeval t;
57         struct udisks_data *data;
58
59         data = s->provider_data;
60
61         if (gettimeofday(&t, NULL) != 0) {
62                 log_err("%s: %s", PROVIDER_NAME, _("gettimeofday failed."));
63                 return;
64         }
65
66         if (data->last_smart_update.tv_sec
67             &&
68             (t.tv_sec - data->last_smart_update.tv_sec < SMART_UPDATE_INTERVAL))
69                 return;
70
71         log_fct("%s: update SMART data for %s", PROVIDER_NAME, data->path);
72
73         variant = g_variant_new_parsed("{'nowakeup': %v}",
74                                        g_variant_new_boolean(TRUE));
75
76         ret = udisks_drive_ata_call_smart_update_sync(ata,
77                                                       variant,
78                                                       NULL,
79                                                       NULL);
80
81         if (!ret)
82                 log_fct("%s: SMART update failed for %s",
83                         PROVIDER_NAME,
84                         data->path);
85
86                 data->last_smart_update = t;
87 }
88
89 void udisks2_psensor_list_update(struct psensor **sensors)
90 {
91         struct psensor *s;
92         GDBusObject *o;
93         UDisksDriveAta *drive_ata;
94         double v;
95         struct udisks_data *data;
96
97         for (; *sensors; sensors++) {
98                 s = *sensors;
99
100                 if (s->type & SENSOR_TYPE_REMOTE)
101                         continue;
102
103                 if (s->type & SENSOR_TYPE_UDISKS2) {
104                         data = (struct udisks_data *)s->provider_data;
105
106                         o = g_dbus_object_manager_get_object(manager,
107                                                              data->path);
108
109                         if (!o)
110                                 continue;
111
112                         g_object_get(o, "drive-ata", &drive_ata, NULL);
113
114                         smart_update(s, drive_ata);
115
116                         v = udisks_drive_ata_get_smart_temperature(drive_ata);
117
118                         psensor_set_current_value(s, kelvin_to_celsius(v));
119
120                         g_object_unref(G_OBJECT(o));
121                 }
122         }
123 }
124
125 void udisks2_psensor_list_append(struct psensor ***sensors, int values_length)
126 {
127         UDisksClient *client;
128         GList *objects, *cur;
129         UDisksDrive *drive;
130         UDisksDriveAta *drive_ata;
131         int i, type;
132         char *id, *name, *chip;
133         const char *path, *drive_id, *drive_model;
134         struct psensor *s;
135         struct udisks_data *data;
136
137         log_fct_enter();
138
139         client = udisks_client_new_sync(NULL, NULL);
140
141         if (!client) {
142                 log_err(_("%s: cannot get the udisks2 client"), PROVIDER_NAME);
143                 log_fct_exit();
144                 return;
145         }
146
147         manager = udisks_client_get_object_manager(client);
148
149         objects = g_dbus_object_manager_get_objects(manager);
150
151         i = 0;
152         for (cur = objects; cur; cur = cur->next) {
153                 path = g_dbus_object_get_object_path(cur->data);
154
155                 g_object_get(cur->data,
156                              "drive", &drive,
157                              "drive-ata", &drive_ata,
158                              NULL);
159
160                 if (!drive) {
161                         log_fct("Not a drive: %s", path);
162                         continue;
163                 }
164
165                 if (!drive_ata) {
166                         log_fct("Not an ATA drive: %s", path);
167                         continue;
168                 }
169
170                 if (!udisks_drive_ata_get_smart_enabled(drive_ata)) {
171                         log_fct("SMART not enabled: %s", path);
172                         continue;
173                 }
174
175                 if (!udisks_drive_ata_get_smart_temperature(drive_ata)) {
176                         log_fct("No temperature available: %s", path);
177                         continue;
178                 }
179
180                 drive_id = udisks_drive_get_id(drive);
181                 if (drive_id) {
182                         id = g_strdup_printf("%s %s", PROVIDER_NAME, drive_id);
183                 } else {
184                         id = g_strdup_printf("%s %d", PROVIDER_NAME, i);
185                         i++;
186                 }
187
188                 drive_model = udisks_drive_get_model(drive);
189                 if (drive_model) {
190                         name = strdup(drive_model);
191                         chip = strdup(drive_model);
192                 } else {
193                         name = strdup(_("Disk"));
194                         chip = strdup(_("Disk"));
195                 }
196
197                 type = SENSOR_TYPE_TEMP | SENSOR_TYPE_UDISKS2 | SENSOR_TYPE_HDD;
198
199                 s = psensor_create(id, name, chip, type, values_length);
200
201                 data = malloc(sizeof(struct udisks_data));
202                 data->path = strdup(path);
203                 memset(&data->last_smart_update, 0, sizeof(struct timeval));
204
205                 s->provider_data = data;
206                 s->provider_data_free_fct = &udisks_data_free;
207
208                 psensor_list_append(sensors, s);
209
210                 g_object_unref(G_OBJECT(cur->data));
211         }
212
213         g_list_free(objects);
214
215         log_fct_exit();
216 }