aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-fsutils.c
blob: d2c615124b03e0d027bffbe3f8b051718c2be110 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
 *
 * Authors: Michael Zucchi <notzed@ximian.com>
 *
 * Copyright 2004 Ximian, Inc. (www.ximian.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of version 2 of the GNU General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

/* This isn't as portable as, say, the stuff in GNU coreutils.  But I care not for OSF1. */
#ifdef HAVE_STATFS
# ifdef HAVE_SYS_VFS_H
#  include <sys/vfs.h>      /* linux interface */
# endif
# ifdef HAVE_SYS_PARAM_H
#  include <sys/param.h>    /* bsd interface */
# endif
# ifdef HAVE_SYS_MOUNT_H
#  include <sys/mount.h>
# endif
#endif

#include <errno.h>
#include <string.h>

#include "e-fsutils.h"

/**
 * e_fsutils_usage:
 * @path: 
 * 
 * Calculate the amount of disk space used by a given path.
 * 
 * Return value: The number of 1024 byte blocks used by the
 * filesystem.
 **/
long e_fsutils_usage(const char *inpath)
{
    DIR *dir;
    struct dirent *d;
    long size = 0;
    GSList *paths;

    /* iterative, depth-first scan, because i can ... */
    paths = g_slist_prepend(NULL, g_strdup(inpath));

    while (paths) {
        char *path = paths->data;

        paths = g_slist_remove_link(paths, paths);

        dir = opendir(path);
        if (dir == NULL) {
            g_free(path);
            goto fail;
        }

        while ((d = readdir(dir))) {
            char *full_path;
            struct stat st;

            if (strcmp(d->d_name, ".") == 0
                || strcmp(d->d_name, "..") == 0)
                continue;
        
            full_path = g_build_filename(path, d->d_name, NULL);
            if (stat(full_path, &st) == -1) {
                g_free(full_path);
                closedir(dir);
                g_free(path);
                goto fail;
            } else if (S_ISDIR(st.st_mode)) {
                paths = g_slist_prepend(paths, full_path);
                full_path = NULL;
            } else if (S_ISREG(st.st_mode)) {
                /* This is in 512 byte blocks.  st_blksize is page size on linux,
                   on *BSD it might be significant. */
                size += st.st_blocks/2;
            }

            g_free(full_path);
        }

        closedir(dir);
        g_free(path);
    }

    return size;

fail:
    g_slist_foreach(paths, (GFunc)g_free, NULL);
    g_slist_free(paths);

    return -1;
}

/**
 * e_fsutils_avail:
 * @path: 
 * 
 * Find the available disk space at the given path.
 * 
 * Return value: -1 if it could not be determined, otherwise the
 * number of disk blocks, expressed as system-independent, 1024 byte
 * blocks.
 **/
long
e_fsutils_avail(const char *path)
{
#ifdef HAVE_STATFS
    struct statfs stfs;

    if (statfs(path, &stfs) == -1)
        return -1;

    /* On linux at least, bavail is in 512 byte blocks */
    /* For BSD this isn't clear, it may be dependent on f_bsize, which on linux is rather, the page size! */
    return stfs.f_bavail / 2;
#else
    errno = ENOSYS;
    return -1;
#endif
}