~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to ksysguard/ksysguardd/Linux/diskstat.c

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    KSysGuard, the KDE System Guard
 
3
 
 
4
    Copyright (c) 2001 Tobias Koenig <tokoe@kde.org>
 
5
 
 
6
    This program is free software; you can redistribute it and/or
 
7
    modify it under the terms of version 2 of the GNU General Public
 
8
    License as published by the Free Software Foundation.
 
9
 
 
10
    This program is distributed in the hope that it will be useful,
 
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
    GNU General Public License for more details.
 
14
 
 
15
    You should have received a copy of the GNU General Public License
 
16
    along with this program; if not, write to the Free Software
 
17
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 
 
19
*/
 
20
 
 
21
#include <config-workspace.h>
 
22
 
 
23
#include <mntent.h>
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <string.h>
 
27
#include <sys/statvfs.h>
 
28
#include <time.h>
 
29
#include <unistd.h>
 
30
#include <ctype.h>
 
31
 
 
32
#include "Command.h"
 
33
#include "ccont.h"
 
34
#include "diskstat.h"
 
35
#include "ksysguardd.h"
 
36
 
 
37
typedef struct {
 
38
    char device[ 256 ];
 
39
    char mntpnt[ 256 ];
 
40
    struct statvfs statvfs;
 
41
} DiskInfo;
 
42
 
 
43
static CONTAINER DiskStatList = 0;
 
44
static CONTAINER OldDiskStatList = 0;
 
45
static struct SensorModul* DiskStatSM;
 
46
char *getMntPnt( const char* cmd );
 
47
 
 
48
static void sanitize(char *str)  {
 
49
    if(str == NULL)
 
50
        return;
 
51
    while (*str != 0)  {
 
52
        if(*str == '\t' || *str == '\n' || *str == '\r' || *str == ' ' || !isascii(*str) )
 
53
            *str = '?';
 
54
        ++str;
 
55
    }
 
56
}
 
57
 
 
58
char *getMntPnt( const char* cmd )
 
59
{
 
60
    static char device[ 1025 ];
 
61
    char* ptr;
 
62
 
 
63
    memset( device, 0, sizeof( device ) );
 
64
    sscanf( cmd, "partitions%1024s", device );
 
65
 
 
66
    ptr = (char*)rindex( device, '/' );
 
67
    *ptr = '\0';
 
68
 
 
69
    return (char*)device;
 
70
}
 
71
 
 
72
/* ----------------------------- public part ------------------------------- */
 
73
 
 
74
static char monitor[ 1024 ];
 
75
static void registerMonitors(const char* mntpnt) {
 
76
    snprintf( monitor, sizeof( monitor ), "partitions%s/usedspace", mntpnt );
 
77
    registerMonitor( monitor, "integer", printDiskStatUsed, printDiskStatUsedInfo, DiskStatSM );
 
78
    snprintf( monitor, sizeof( monitor ), "partitions%s/freespace", mntpnt );
 
79
    registerMonitor( monitor, "integer", printDiskStatFree, printDiskStatFreeInfo, DiskStatSM );
 
80
    snprintf( monitor, sizeof( monitor ), "partitions%s/filllevel", mntpnt );
 
81
    registerMonitor( monitor, "integer", printDiskStatPercent, printDiskStatPercentInfo, DiskStatSM );
 
82
}
 
83
static void removeMonitors(const char* mntpnt) {
 
84
    snprintf( monitor, sizeof( monitor ), "partitions%s/usedspace", mntpnt );
 
85
    removeMonitor( monitor );
 
86
    snprintf( monitor, sizeof( monitor ), "partitions%s/freespace", mntpnt );
 
87
    removeMonitor( monitor );
 
88
    snprintf( monitor, sizeof( monitor ), "partitions%s/filllevel", mntpnt );
 
89
    removeMonitor( monitor );
 
90
}
 
91
 
 
92
void initDiskStat( struct SensorModul* sm )
 
93
{
 
94
    DiskInfo* disk_info;
 
95
 
 
96
    DiskStatList = NULL;
 
97
    OldDiskStatList = NULL;
 
98
    DiskStatSM = sm;
 
99
    if ( updateDiskStat() < 0 )
 
100
        return;
 
101
 
 
102
    registerMonitor( "partitions/list", "listview", printDiskStat, printDiskStatInfo, sm );
 
103
 
 
104
    for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
 
105
        registerMonitors(disk_info->mntpnt);
 
106
    }
 
107
}
 
108
 
 
109
void exitDiskStat( void )
 
110
{
 
111
    DiskInfo* disk_info;
 
112
 
 
113
    removeMonitor( "partitions/list" );
 
114
 
 
115
    for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
 
116
        removeMonitors(disk_info->mntpnt);
 
117
    }
 
118
 
 
119
    destr_ctnr( DiskStatList, free );
 
120
    if(OldDiskStatList)
 
121
        destr_ctnr( OldDiskStatList, free );
 
122
}
 
123
 
 
124
void checkDiskStat( void )
 
125
{
 
126
    updateDiskStat();
 
127
    DiskInfo* disk_info_new;
 
128
    DiskInfo* disk_info_old;
 
129
    int changed = 0;
 
130
    for ( disk_info_new = first_ctnr( DiskStatList ); disk_info_new; disk_info_new = next_ctnr( DiskStatList ) ) {
 
131
        int found = 0;
 
132
        for ( disk_info_old = first_ctnr( OldDiskStatList ); disk_info_old; disk_info_old = next_ctnr( OldDiskStatList ) ) {
 
133
            if(strcmp(disk_info_new->mntpnt, disk_info_old->mntpnt) == 0) {
 
134
                free( remove_ctnr( OldDiskStatList ) );
 
135
                found = 1;
 
136
                continue;
 
137
            }
 
138
        }
 
139
        if(!found) {
 
140
            /* register all the devices that did not exist before*/
 
141
            registerMonitors(disk_info_new->mntpnt);
 
142
            changed++;
 
143
        }
 
144
    }
 
145
    /*Now remove all the devices that do not exist anymore*/
 
146
    for ( disk_info_old = first_ctnr( OldDiskStatList ); disk_info_old; disk_info_old = next_ctnr( OldDiskStatList ) ) {
 
147
        removeMonitors(disk_info_old->mntpnt);
 
148
        changed++;
 
149
    }
 
150
    destr_ctnr( OldDiskStatList, free );
 
151
    OldDiskStatList = NULL;
 
152
    updateDiskStat();
 
153
    if(changed)
 
154
        print_error( "RECONFIGURE" ); /*Let ksysguard know that we've added a sensor*/
 
155
}
 
156
 
 
157
int updateDiskStat( void )
 
158
{
 
159
    DiskInfo *disk_info;
 
160
    FILE *fh;
 
161
    struct mntent *mnt_info;
 
162
 
 
163
    if ( ( fh = setmntent( "/etc/mtab", "r" ) ) == NULL ) {
 
164
        print_error( "Cannot open \'/etc/mtab\'!\n" );
 
165
        return -1;
 
166
    }
 
167
    if(OldDiskStatList == 0) {
 
168
        OldDiskStatList = DiskStatList;
 
169
        DiskStatList = new_ctnr();
 
170
    } else {
 
171
        empty_ctnr(DiskStatList);
 
172
    }
 
173
 
 
174
    while ( ( mnt_info = getmntent( fh ) ) != NULL ) {
 
175
        /*
 
176
         * An entry which device name doesn't start with a '/' is
 
177
         * either a dummy file system or a network file system.
 
178
         * Add special handling for smbfs and cifs as is done by
 
179
         * coreutils as well.
 
180
         */
 
181
        if ( (mnt_info->mnt_fsname[0] != '/') ||
 
182
             !strcmp( mnt_info->mnt_type, "smbfs" ) ||
 
183
             !strcmp( mnt_info->mnt_type, "cifs" ) ||
 
184
             !strcmp( mnt_info->mnt_type, "proc" ) ||
 
185
             !strcmp( mnt_info->mnt_type, "devfs" ) ||
 
186
             !strcmp( mnt_info->mnt_type, "usbfs" ) ||
 
187
             !strcmp( mnt_info->mnt_type, "sysfs" ) ||
 
188
             !strcmp( mnt_info->mnt_type, "tmpfs" ) ||
 
189
             !strcmp( mnt_info->mnt_type, "devpts" ) )
 
190
            continue;  /* Skip these file systems */
 
191
 
 
192
        if ( ( disk_info = (DiskInfo *)malloc( sizeof( DiskInfo ) ) ) == NULL )
 
193
            continue;
 
194
 
 
195
        memset( disk_info, 0, sizeof( DiskInfo ) );
 
196
 
 
197
        if ( statvfs( mnt_info->mnt_dir, &(disk_info->statvfs) ) < 0 )
 
198
            continue;
 
199
 
 
200
        strncpy( disk_info->device, mnt_info->mnt_fsname, sizeof( disk_info->device ) );
 
201
        disk_info->device[ sizeof(disk_info->device) -1] = 0;
 
202
 
 
203
        strncpy( disk_info->mntpnt, mnt_info->mnt_dir, sizeof( disk_info->mntpnt ) );
 
204
        disk_info->mntpnt[ sizeof(disk_info->mntpnt) - 1] = 0;
 
205
        sanitize(disk_info->mntpnt);
 
206
 
 
207
        push_ctnr( DiskStatList, disk_info );
 
208
    }
 
209
    endmntent( fh );
 
210
 
 
211
    return 0;
 
212
}
 
213
 
 
214
int calculatePercentageUsed( unsigned long totalSizeKB, unsigned long available) {
 
215
    if (!available)
 
216
        return 0;
 
217
 
 
218
    unsigned long totalSizeKBdividedBy100 = (50 + totalSizeKB )/ 100;
 
219
    if (!totalSizeKBdividedBy100)
 
220
        return 0;
 
221
 
 
222
    int percentageUsed = 100 - available / totalSizeKBdividedBy100; /* Percentage is 1 - available / totalSizeKB, meaning that we count root-only reserved space as "used" here */
 
223
    /* If we have rounded down to 0%, make it 1%, like "df" does */
 
224
    if (percentageUsed == 0)
 
225
        return 1;
 
226
    return percentageUsed;
 
227
}
 
228
 
 
229
void printDiskStat( const char* cmd )
 
230
{
 
231
    DiskInfo* disk_info;
 
232
 
 
233
    (void)cmd;
 
234
    for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
 
235
        /* See man statvfs(2) for meaning of fields */
 
236
        unsigned long totalSizeKB =  disk_info->statvfs.f_blocks * (disk_info->statvfs.f_frsize/1024);
 
237
        unsigned long usedKB = totalSizeKB - (disk_info->statvfs.f_bfree * (disk_info->statvfs.f_bsize/1024)); /* used is the total size minus free blocks including those for root only */
 
238
        unsigned long available = disk_info->statvfs.f_bavail * (disk_info->statvfs.f_bsize/1024); /* available is only those for non-root.  So available + used != total because some are reserved for root */
 
239
        int percentageUsed = calculatePercentageUsed(totalSizeKB, available);
 
240
        output( "%s\t%ld\t%ld\t%ld\t%d\t%s\n",
 
241
                disk_info->device,
 
242
                totalSizeKB,
 
243
                usedKB,
 
244
                available,
 
245
                percentageUsed,
 
246
                disk_info->mntpnt );
 
247
    }
 
248
 
 
249
    output( "\n" );
 
250
}
 
251
 
 
252
void printDiskStatInfo( const char* cmd )
 
253
{
 
254
    (void)cmd;
 
255
    output( "Device\tSize\tUsed\tAvailable\tUsed %%\tMount point\nM\tKB\tKB\tKB\t%%\ts\n" );
 
256
}
 
257
 
 
258
void printDiskStatUsed( const char* cmd )
 
259
{
 
260
    char *mntpnt = (char*)getMntPnt( cmd );
 
261
    DiskInfo* disk_info;
 
262
 
 
263
    for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
 
264
        if ( !strcmp( mntpnt, disk_info->mntpnt ) ) {
 
265
            unsigned long totalSizeKB =  disk_info->statvfs.f_blocks * (disk_info->statvfs.f_frsize/1024);
 
266
            unsigned long usedKB = totalSizeKB - (disk_info->statvfs.f_bfree * (disk_info->statvfs.f_bsize/1024)); /* used is the total size minus free blocks including those for root only */
 
267
            output( "%ld\n", usedKB );
 
268
        }
 
269
    }
 
270
 
 
271
    output( "\n" );
 
272
}
 
273
 
 
274
void printDiskStatUsedInfo( const char* cmd )
 
275
{
 
276
    (void)cmd;
 
277
    output( "Used\t0\t0\tKB\n" );
 
278
}
 
279
 
 
280
void printDiskStatFree( const char* cmd )
 
281
{
 
282
    char *mntpnt = (char*)getMntPnt( cmd );
 
283
    DiskInfo* disk_info;
 
284
 
 
285
    for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
 
286
        if ( !strcmp( mntpnt, disk_info->mntpnt ) ) {
 
287
            unsigned long available = disk_info->statvfs.f_bavail * (disk_info->statvfs.f_bsize/1024); /* available is only those for non-root.  So available + used != total because some are reserved for root */
 
288
            output( "%ld\n", available );
 
289
        }
 
290
    }
 
291
    output( "\n" );
 
292
}
 
293
 
 
294
void printDiskStatFreeInfo( const char* cmd )
 
295
{
 
296
    (void)cmd;
 
297
    output( "Available\t0\t0\tKB\n" );
 
298
}
 
299
 
 
300
void printDiskStatPercent( const char* cmd )
 
301
{
 
302
    char *mntpnt = (char*)getMntPnt( cmd );
 
303
    DiskInfo* disk_info;
 
304
 
 
305
    for ( disk_info = first_ctnr( DiskStatList ); disk_info; disk_info = next_ctnr( DiskStatList ) ) {
 
306
        if ( !strcmp( mntpnt, disk_info->mntpnt ) ) {
 
307
            unsigned long totalSizeKB =  disk_info->statvfs.f_blocks * (disk_info->statvfs.f_frsize/1024);
 
308
            unsigned long available = disk_info->statvfs.f_bavail * (disk_info->statvfs.f_bsize/1024); /* available is only those for non-root.  So available + used != total because some are reserved for root */
 
309
 
 
310
            int percentageUsed = calculatePercentageUsed(totalSizeKB, available);
 
311
            output( "%d\n", percentageUsed );
 
312
        }
 
313
    }
 
314
 
 
315
    output( "\n" );
 
316
}
 
317
 
 
318
void printDiskStatPercentInfo( const char* cmd )
 
319
{
 
320
    (void)cmd;
 
321
    output( "Percentage Used\t0\t100\t%%\n" );
 
322
}