aboutsummaryrefslogtreecommitdiffstats
path: root/e-util/e-fsutils.c
blob: 28b434f291e068642086109c3ad2fcd108b230d7 (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
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) version 3.
 *
 * 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with the program; if not, see <http://www.gnu.org/licenses/>  
 *
 *
 * Authors:
 *      Michael Zucchi <notzed@ximian.com>
 *
 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
 *
 */

#include <config.h>

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

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

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

#include <glib.h>
#include <glib/gstdio.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)
{
    GDir *dir;
    const char *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 = g_dir_open(path, 0, NULL);
        if (dir == NULL) {
            g_free(path);
            goto fail;
        }

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

            full_path = g_build_filename(path, d, NULL);
            if (g_stat(full_path, &st) == -1) {
                g_free(full_path);
                g_dir_close(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. */
#ifndef G_OS_WIN32
                size += st.st_blocks/2;
#endif
            }

            g_free(full_path);
        }

        g_dir_close(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)
{
#if defined(HAVE_STATVFS)
    struct statvfs stfs;

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

    /* Assumes that frsize === power of 2 */
    if (stfs.f_frsize >= 1024)
        return stfs.f_bavail * (stfs.f_frsize / 1024);
    else
        return stfs.f_bavail / (1024 / stfs.f_frsize);
#elif defined(HAVE_STATFS)
    struct statfs stfs;

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

    /* For BSD this isn't clear, it may be dependent on f_bsize */
    return stfs.f_bavail / 2;
#else
    errno = ENOSYS;
    return -1;
#endif
}