173f9b8cfSDoug MacEachern/*
273f9b8cfSDoug MacEachern * Copyright (c) 2004-2005, 2007-2008 Hyperic, Inc.
373f9b8cfSDoug MacEachern * Copyright (c) 2009 SpringSource, Inc.
473f9b8cfSDoug MacEachern * Copyright (c) 2010 VMware, Inc.
573f9b8cfSDoug MacEachern *
673f9b8cfSDoug MacEachern * Licensed under the Apache License, Version 2.0 (the "License");
773f9b8cfSDoug MacEachern * you may not use this file except in compliance with the License.
873f9b8cfSDoug MacEachern * You may obtain a copy of the License at
973f9b8cfSDoug MacEachern *
1073f9b8cfSDoug MacEachern *     http://www.apache.org/licenses/LICENSE-2.0
1173f9b8cfSDoug MacEachern *
1273f9b8cfSDoug MacEachern * Unless required by applicable law or agreed to in writing, software
1373f9b8cfSDoug MacEachern * distributed under the License is distributed on an "AS IS" BASIS,
1473f9b8cfSDoug MacEachern * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1573f9b8cfSDoug MacEachern * See the License for the specific language governing permissions and
1673f9b8cfSDoug MacEachern * limitations under the License.
1773f9b8cfSDoug MacEachern */
1873f9b8cfSDoug MacEachern
19dffe0da8SDoug MacEachern/* ====================================================================
20dffe0da8SDoug MacEachern * The Apache Software License, Version 1.1
21dffe0da8SDoug MacEachern *
22dffe0da8SDoug MacEachern * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
23dffe0da8SDoug MacEachern * reserved.
24dffe0da8SDoug MacEachern *
25dffe0da8SDoug MacEachern * Redistribution and use in source and binary forms, with or without
26dffe0da8SDoug MacEachern * modification, are permitted provided that the following conditions
27dffe0da8SDoug MacEachern * are met:
28dffe0da8SDoug MacEachern *
29dffe0da8SDoug MacEachern * 1. Redistributions of source code must retain the above copyright
30dffe0da8SDoug MacEachern *    notice, this list of conditions and the following disclaimer.
31dffe0da8SDoug MacEachern *
32dffe0da8SDoug MacEachern * 2. Redistributions in binary form must reproduce the above copyright
33dffe0da8SDoug MacEachern *    notice, this list of conditions and the following disclaimer in
34dffe0da8SDoug MacEachern *    the documentation and/or other materials provided with the
35dffe0da8SDoug MacEachern *    distribution.
36dffe0da8SDoug MacEachern *
37dffe0da8SDoug MacEachern * 3. The end-user documentation included with the redistribution,
38dffe0da8SDoug MacEachern *    if any, must include the following acknowledgment:
39dffe0da8SDoug MacEachern *       "This product includes software developed by the
40dffe0da8SDoug MacEachern *        Apache Software Foundation (http://www.apache.org/)."
41dffe0da8SDoug MacEachern *    Alternately, this acknowledgment may appear in the software itself,
42dffe0da8SDoug MacEachern *    if and wherever such third-party acknowledgments normally appear.
43dffe0da8SDoug MacEachern *
44dffe0da8SDoug MacEachern * 4. The names "Apache" and "Apache Software Foundation" must
45dffe0da8SDoug MacEachern *    not be used to endorse or promote products derived from this
46dffe0da8SDoug MacEachern *    software without prior written permission. For written
47dffe0da8SDoug MacEachern *    permission, please contact apache@apache.org.
48dffe0da8SDoug MacEachern *
49dffe0da8SDoug MacEachern * 5. Products derived from this software may not be called "Apache",
50dffe0da8SDoug MacEachern *    nor may "Apache" appear in their name, without prior written
51dffe0da8SDoug MacEachern *    permission of the Apache Software Foundation.
52dffe0da8SDoug MacEachern *
53dffe0da8SDoug MacEachern * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
54dffe0da8SDoug MacEachern * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
55dffe0da8SDoug MacEachern * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
56dffe0da8SDoug MacEachern * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
57dffe0da8SDoug MacEachern * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58dffe0da8SDoug MacEachern * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
59dffe0da8SDoug MacEachern * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
60dffe0da8SDoug MacEachern * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
61dffe0da8SDoug MacEachern * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
62dffe0da8SDoug MacEachern * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
63dffe0da8SDoug MacEachern * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64dffe0da8SDoug MacEachern * SUCH DAMAGE.
65dffe0da8SDoug MacEachern * ====================================================================
66dffe0da8SDoug MacEachern *
67dffe0da8SDoug MacEachern * This software consists of voluntary contributions made by many
68dffe0da8SDoug MacEachern * individuals on behalf of the Apache Software Foundation.  For more
69dffe0da8SDoug MacEachern * information on the Apache Software Foundation, please see
70dffe0da8SDoug MacEachern * <http://www.apache.org/>.
71dffe0da8SDoug MacEachern */
72dffe0da8SDoug MacEachern
736cdf6aeaSDoug MacEachern#ifndef WIN32
74ef1a02ebSDoug MacEachern#  ifdef _AIX
75ef1a02ebSDoug MacEachern#    define _LARGE_FILES
76ef1a02ebSDoug MacEachern#  else
77ef1a02ebSDoug MacEachern#    define _FILE_OFFSET_BITS 64
78ef1a02ebSDoug MacEachern#    define _LARGEFILE64_SOURCE
79ef1a02ebSDoug MacEachern#  endif
806cdf6aeaSDoug MacEachern#endif
81e69ec3d9SDoug MacEachern
82cb8eb6b1SDoug MacEachern#include "sigar.h"
83cb8eb6b1SDoug MacEachern
84cb8eb6b1SDoug MacEachern#ifndef WIN32
8564a6f419SDoug MacEachern#if defined(__FreeBSD__) || defined(__OpenBSD__)
8664a6f419SDoug MacEachern# include <sys/param.h>
8764a6f419SDoug MacEachern# include <sys/mount.h>
8864a6f419SDoug MacEachern#else
8964a6f419SDoug MacEachern# include <sys/statvfs.h>
9064a6f419SDoug MacEachern# define HAVE_STATVFS
9164a6f419SDoug MacEachern#endif
92cb8eb6b1SDoug MacEachern#include <errno.h>
93cb8eb6b1SDoug MacEachern
94858b0343STrond Norbye#include "sigar_private.h"
95858b0343STrond Norbye#include "sigar_util.h"
96858b0343STrond Norbye
97cb8eb6b1SDoug MacEachern#define SIGAR_FS_BLOCKS_TO_BYTES(val, bsize) ((val * bsize) >> 1)
98cb8eb6b1SDoug MacEachern
99cb8eb6b1SDoug MacEachernint sigar_statvfs(sigar_t *sigar,
100cb8eb6b1SDoug MacEachern                  const char *dirname,
101cb8eb6b1SDoug MacEachern                  sigar_file_system_usage_t *fsusage)
102cb8eb6b1SDoug MacEachern{
103cb8eb6b1SDoug MacEachern    sigar_uint64_t val, bsize;
10464a6f419SDoug MacEachern#ifdef HAVE_STATVFS
10564a6f419SDoug MacEachern    struct statvfs buf;
10626872fddSDoug MacEachern    int status =
10764a6f419SDoug MacEachern# if defined(__sun) && !defined(_LP64)
10826872fddSDoug MacEachern        /* http://bugs.opensolaris.org/view_bug.do?bug_id=4462986 */
10926872fddSDoug MacEachern        statvfs(dirname, (void *)&buf);
11064a6f419SDoug MacEachern# else
11126872fddSDoug MacEachern        statvfs(dirname, &buf);
11264a6f419SDoug MacEachern# endif
11364a6f419SDoug MacEachern#else
11464a6f419SDoug MacEachern    struct statfs buf;
11564a6f419SDoug MacEachern    int status = statfs(dirname, &buf);
11626872fddSDoug MacEachern#endif
117cb8eb6b1SDoug MacEachern
11826872fddSDoug MacEachern    if (status != 0) {
119cb8eb6b1SDoug MacEachern        return errno;
120cb8eb6b1SDoug MacEachern    }
121cb8eb6b1SDoug MacEachern
12264a6f419SDoug MacEachern#ifdef HAVE_STATVFS
123cb8eb6b1SDoug MacEachern    bsize = buf.f_frsize / 512;
12464a6f419SDoug MacEachern#else
12564a6f419SDoug MacEachern    bsize = buf.f_bsize / 512;
12664a6f419SDoug MacEachern#endif
127cb8eb6b1SDoug MacEachern    val = buf.f_blocks;
128cb8eb6b1SDoug MacEachern    fsusage->total = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize);
129cb8eb6b1SDoug MacEachern    val = buf.f_bfree;
130cb8eb6b1SDoug MacEachern    fsusage->free  = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize);
131cb8eb6b1SDoug MacEachern    val = buf.f_bavail;
132cb8eb6b1SDoug MacEachern    fsusage->avail = SIGAR_FS_BLOCKS_TO_BYTES(val, bsize);
133cb8eb6b1SDoug MacEachern    fsusage->used  = fsusage->total - fsusage->free;
134cb8eb6b1SDoug MacEachern    fsusage->files = buf.f_files;
135cb8eb6b1SDoug MacEachern    fsusage->free_files = buf.f_ffree;
136cb8eb6b1SDoug MacEachern
137cb8eb6b1SDoug MacEachern    return SIGAR_OK;
138cb8eb6b1SDoug MacEachern}
139cb8eb6b1SDoug MacEachern#endif
140cb8eb6b1SDoug MacEachern
141dffe0da8SDoug MacEachern/*
142dffe0da8SDoug MacEachern * whittled down version of apr/file_info/{unix,win32}/filestat.c
143dffe0da8SDoug MacEachern * to fillin sigar_fileattrs_t
144dffe0da8SDoug MacEachern */
145dffe0da8SDoug MacEachern#include "sigar_fileinfo.h"
146e69ec3d9SDoug MacEachern#include "sigar_log.h"
147e69ec3d9SDoug MacEachern
148e69ec3d9SDoug MacEachern#ifndef SIGAR_ZERO
149e69ec3d9SDoug MacEachern#define SIGAR_ZERO(s) \
150e69ec3d9SDoug MacEachern    memset(s, '\0', sizeof(*(s)))
151e69ec3d9SDoug MacEachern#endif
152e69ec3d9SDoug MacEachern
15335a3672cSDoug MacEachern#ifdef WIN32
15435a3672cSDoug MacEachern#include <windows.h>
15535a3672cSDoug MacEachernsigar_uint64_t sigar_FileTimeToTime(FILETIME *ft);
15635a3672cSDoug MacEachern#else
157e69ec3d9SDoug MacEachern#include <string.h>
158e69ec3d9SDoug MacEachern#endif
159dffe0da8SDoug MacEachern
160dffe0da8SDoug MacEachernstatic const char* types[] = {
161dffe0da8SDoug MacEachern    "none",
162dffe0da8SDoug MacEachern    "regular",
163dffe0da8SDoug MacEachern    "directory",
164dffe0da8SDoug MacEachern    "character device",
165dffe0da8SDoug MacEachern    "block device",
166dffe0da8SDoug MacEachern    "pipe",
167dffe0da8SDoug MacEachern    "symbolic link",
168dffe0da8SDoug MacEachern    "socket",
169dffe0da8SDoug MacEachern    "unknown"
170dffe0da8SDoug MacEachern};
171dffe0da8SDoug MacEachern
172dffe0da8SDoug MacEachernSIGAR_DECLARE(const char *)
173dffe0da8SDoug MacEachernsigar_file_attrs_type_string_get(sigar_file_type_e type)
174dffe0da8SDoug MacEachern{
175dffe0da8SDoug MacEachern    if ((type < SIGAR_FILETYPE_NOFILE) ||
176dffe0da8SDoug MacEachern        (type > SIGAR_FILETYPE_UNKFILE))
177dffe0da8SDoug MacEachern    {
178dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_UNKFILE;
179dffe0da8SDoug MacEachern    }
180dffe0da8SDoug MacEachern
181dffe0da8SDoug MacEachern    return types[type];
182dffe0da8SDoug MacEachern}
183dffe0da8SDoug MacEachern
184dffe0da8SDoug MacEachernstatic const sigar_uint64_t perm_modes[] = {
185dffe0da8SDoug MacEachern    SIGAR_UREAD, SIGAR_UWRITE, SIGAR_UEXECUTE,
186dffe0da8SDoug MacEachern    SIGAR_GREAD, SIGAR_GWRITE, SIGAR_GEXECUTE,
187dffe0da8SDoug MacEachern    SIGAR_WREAD, SIGAR_WWRITE, SIGAR_WEXECUTE
188dffe0da8SDoug MacEachern};
189dffe0da8SDoug MacEachern
190dffe0da8SDoug MacEachernstatic const char perm_chars[] = "rwx";
191dffe0da8SDoug MacEachern
192dffe0da8SDoug MacEachernSIGAR_DECLARE(char *)
193dffe0da8SDoug MacEachernsigar_file_attrs_permissions_string_get(sigar_uint64_t permissions,
194dffe0da8SDoug MacEachern                                        char *str)
195dffe0da8SDoug MacEachern{
196dffe0da8SDoug MacEachern    char *ptr = str;
197dffe0da8SDoug MacEachern    int i=0, j=0;
198dffe0da8SDoug MacEachern
199dffe0da8SDoug MacEachern    for (i=0; i<9; i+=3) {
200dffe0da8SDoug MacEachern        for (j=0; j<3; j++) {
201dffe0da8SDoug MacEachern            if (permissions & perm_modes[i+j]) {
202dffe0da8SDoug MacEachern                *ptr = perm_chars[j];
203dffe0da8SDoug MacEachern            }
204dffe0da8SDoug MacEachern            else {
205dffe0da8SDoug MacEachern                *ptr = '-';
206dffe0da8SDoug MacEachern            }
207dffe0da8SDoug MacEachern            ptr++;
208dffe0da8SDoug MacEachern        }
209dffe0da8SDoug MacEachern    }
210dffe0da8SDoug MacEachern
211dffe0da8SDoug MacEachern    *ptr = '\0';
212dffe0da8SDoug MacEachern    return str;
213dffe0da8SDoug MacEachern}
214dffe0da8SDoug MacEachern
215dffe0da8SDoug MacEachernstatic const int perm_int[] = {
216dffe0da8SDoug MacEachern    400, 200, 100,
217dffe0da8SDoug MacEachern     40,  20,  10,
218dffe0da8SDoug MacEachern      4,   2,   1
219dffe0da8SDoug MacEachern};
220dffe0da8SDoug MacEachern
221dffe0da8SDoug MacEachernSIGAR_DECLARE(int)sigar_file_attrs_mode_get(sigar_uint64_t permissions)
222dffe0da8SDoug MacEachern{
223dffe0da8SDoug MacEachern    int i=0;
224dffe0da8SDoug MacEachern    int perms = 0;
225dffe0da8SDoug MacEachern
226dffe0da8SDoug MacEachern    /* no doubt there is some fancy bitshifting
227dffe0da8SDoug MacEachern     * to convert, but this works fine.
228dffe0da8SDoug MacEachern     */
229dffe0da8SDoug MacEachern    for (i=0; i<9; i++) {
230dffe0da8SDoug MacEachern        if (permissions & perm_modes[i]) {
231dffe0da8SDoug MacEachern            perms += perm_int[i];
232dffe0da8SDoug MacEachern        }
233dffe0da8SDoug MacEachern    }
234dffe0da8SDoug MacEachern
235dffe0da8SDoug MacEachern    return perms;
236dffe0da8SDoug MacEachern}
237dffe0da8SDoug MacEachern
238dffe0da8SDoug MacEachern#define IS_DOTDIR(dir) \
239dffe0da8SDoug MacEachern    ((dir[0] == '.') && (!dir[1] || ((dir[1] == '.') && !dir[2])))
240dffe0da8SDoug MacEachern
241f8060d5cSDoug MacEachern#define DIR_STAT_WARN() \
242f8060d5cSDoug MacEachern    sigar_log_printf(sigar, SIGAR_LOG_WARN, \
243f8060d5cSDoug MacEachern                     "dir_stat: cannot stat `%s': %s", \
244f8060d5cSDoug MacEachern                     name, \
245f8060d5cSDoug MacEachern                     sigar_strerror(sigar, status))
246f8060d5cSDoug MacEachern
247e44f7a85SDoug MacEachern#if defined(NETWARE)
248e44f7a85SDoug MacEachern
249f2433577SDoug MacEachernint sigar_dir_stat_get(sigar_t *sigar,
250f2433577SDoug MacEachern                       const char *dir,
251f2433577SDoug MacEachern                       sigar_dir_stat_t *dirstats)
252f2433577SDoug MacEachern{
253f2433577SDoug MacEachern    return SIGAR_ENOTIMPL;
254f2433577SDoug MacEachern}
255f2433577SDoug MacEachern
256f2433577SDoug MacEachernint sigar_file_attrs_get(sigar_t *sigar,
257f2433577SDoug MacEachern                         const char *file,
258f2433577SDoug MacEachern                         sigar_file_attrs_t *fileattrs)
259f2433577SDoug MacEachern{
260f2433577SDoug MacEachern    return SIGAR_ENOTIMPL;
261f2433577SDoug MacEachern}
262f2433577SDoug MacEachern
263f38169afSDoug MacEachernint sigar_link_attrs_get(sigar_t *sigar,
264f38169afSDoug MacEachern                         const char *file,
265f38169afSDoug MacEachern                         sigar_file_attrs_t *fileattrs)
266f38169afSDoug MacEachern{
267f38169afSDoug MacEachern    return SIGAR_ENOTIMPL;
268f38169afSDoug MacEachern}
269f38169afSDoug MacEachern
270e44f7a85SDoug MacEachern#elif defined(WIN32)
271dffe0da8SDoug MacEachern
2727345b920SDoug MacEachern#include <accctrl.h>
2737345b920SDoug MacEachern#include <aclapi.h>
2747345b920SDoug MacEachern
275dffe0da8SDoug MacEachernstatic void fillin_fileattrs(sigar_file_attrs_t *finfo,
276dffe0da8SDoug MacEachern                             WIN32_FILE_ATTRIBUTE_DATA *wininfo,
277dffe0da8SDoug MacEachern                             int linkinfo)
278dffe0da8SDoug MacEachern{
279dffe0da8SDoug MacEachern    DWORD *sizes = &wininfo->nFileSizeHigh;
280dffe0da8SDoug MacEachern
28135a3672cSDoug MacEachern    finfo->atime = sigar_FileTimeToTime(&wininfo->ftLastAccessTime) / 1000;
28235a3672cSDoug MacEachern    finfo->ctime = sigar_FileTimeToTime(&wininfo->ftCreationTime) / 1000;
28335a3672cSDoug MacEachern    finfo->mtime = sigar_FileTimeToTime(&wininfo->ftLastWriteTime) / 1000;
284dffe0da8SDoug MacEachern
2856cdf6aeaSDoug MacEachern    finfo->size =
2866cdf6aeaSDoug MacEachern        (sigar_uint64_t)sizes[1] | ((sigar_uint64_t)sizes[0] << 32);
287dffe0da8SDoug MacEachern
288dffe0da8SDoug MacEachern    if (linkinfo &&
289dffe0da8SDoug MacEachern        (wininfo->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
290dffe0da8SDoug MacEachern        finfo->type = SIGAR_FILETYPE_LNK;
291dffe0da8SDoug MacEachern    }
292dffe0da8SDoug MacEachern    else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
293dffe0da8SDoug MacEachern        finfo->type = SIGAR_FILETYPE_DIR;
294dffe0da8SDoug MacEachern    }
295dffe0da8SDoug MacEachern    else {
296dffe0da8SDoug MacEachern        finfo->type = SIGAR_FILETYPE_REG;
297dffe0da8SDoug MacEachern    }
298dffe0da8SDoug MacEachern}
299dffe0da8SDoug MacEachern
3007345b920SDoug MacEachernstatic sigar_uint64_t convert_perms(ACCESS_MASK acc, sigar_uint64_t scope)
3017345b920SDoug MacEachern{
3027345b920SDoug MacEachern    sigar_uint64_t perms = 0;
3037345b920SDoug MacEachern    if (acc & FILE_EXECUTE) {
3047345b920SDoug MacEachern        perms |= SIGAR_WEXECUTE;
3057345b920SDoug MacEachern    }
3067345b920SDoug MacEachern    if (acc & FILE_WRITE_DATA) {
3077345b920SDoug MacEachern        perms |= SIGAR_WWRITE;
3087345b920SDoug MacEachern    }
3097345b920SDoug MacEachern    if (acc & FILE_READ_DATA) {
3107345b920SDoug MacEachern        perms |= SIGAR_WREAD;
3117345b920SDoug MacEachern    }
3127345b920SDoug MacEachern
3137345b920SDoug MacEachern    return (perms << scope);
3147345b920SDoug MacEachern}
3157345b920SDoug MacEachern
3167345b920SDoug MacEachernstatic int get_security_info(sigar_t *sigar,
3177345b920SDoug MacEachern                             const char *file,
3187345b920SDoug MacEachern                             sigar_file_attrs_t *fileattrs)
3197345b920SDoug MacEachern{
3207345b920SDoug MacEachern    DWORD retval;
3217345b920SDoug MacEachern    PSID user = NULL, group = NULL, world = NULL;
3227345b920SDoug MacEachern    PACL dacl = NULL;
3237345b920SDoug MacEachern    PSECURITY_DESCRIPTOR pdesc = NULL;
3247345b920SDoug MacEachern    SECURITY_INFORMATION sinfo =
3257345b920SDoug MacEachern        OWNER_SECURITY_INFORMATION |
32642d0b984STrond Norbye        GROUP_SECURITY_INFORMATION |
3277345b920SDoug MacEachern        DACL_SECURITY_INFORMATION;
3287345b920SDoug MacEachern    TRUSTEE ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID};
3297345b920SDoug MacEachern    ACCESS_MASK acc;
3307345b920SDoug MacEachern    SID_IDENTIFIER_AUTHORITY auth = SECURITY_WORLD_SID_AUTHORITY;
3317345b920SDoug MacEachern
3327345b920SDoug MacEachern    retval = GetNamedSecurityInfo((char *)file,
3337345b920SDoug MacEachern                                  SE_FILE_OBJECT,
3347345b920SDoug MacEachern                                  sinfo,
3357345b920SDoug MacEachern                                  &user,
3367345b920SDoug MacEachern                                  &group,
3377345b920SDoug MacEachern                                  &dacl,
3387345b920SDoug MacEachern                                  NULL,
3397345b920SDoug MacEachern                                  &pdesc);
3407345b920SDoug MacEachern
3417345b920SDoug MacEachern    if (retval != ERROR_SUCCESS) {
3427345b920SDoug MacEachern        return retval;
3437345b920SDoug MacEachern    }
3447345b920SDoug MacEachern
3457345b920SDoug MacEachern    if (!AllocateAndInitializeSid(&auth, 1, SECURITY_WORLD_RID,
3467345b920SDoug MacEachern                                  0, 0, 0, 0, 0, 0, 0, &world))
3477345b920SDoug MacEachern    {
3487345b920SDoug MacEachern        world = NULL;
3497345b920SDoug MacEachern    }
3507345b920SDoug MacEachern
3517345b920SDoug MacEachern    ident.TrusteeType = TRUSTEE_IS_USER;
3527345b920SDoug MacEachern    ident.ptstrName = user;
3537345b920SDoug MacEachern    if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
3547345b920SDoug MacEachern        fileattrs->permissions |= convert_perms(acc, 8);
3557345b920SDoug MacEachern    }
3567345b920SDoug MacEachern
3577345b920SDoug MacEachern    ident.TrusteeType = TRUSTEE_IS_GROUP;
3587345b920SDoug MacEachern    ident.ptstrName = group;
3597345b920SDoug MacEachern    if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
3607345b920SDoug MacEachern        fileattrs->permissions |= convert_perms(acc, 4);
3617345b920SDoug MacEachern    }
3627345b920SDoug MacEachern
3637345b920SDoug MacEachern    if (world) {
3647345b920SDoug MacEachern        ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
3657345b920SDoug MacEachern        ident.ptstrName = world;
3667345b920SDoug MacEachern        if (GetEffectiveRightsFromAcl(dacl, &ident, &acc) == ERROR_SUCCESS) {
3677345b920SDoug MacEachern            fileattrs->permissions |= convert_perms(acc, 0);
3687345b920SDoug MacEachern        }
3697345b920SDoug MacEachern    }
3707345b920SDoug MacEachern
3717345b920SDoug MacEachern    if (world) {
3727345b920SDoug MacEachern        FreeSid(world);
3737345b920SDoug MacEachern    }
3747345b920SDoug MacEachern
3757345b920SDoug MacEachern    LocalFree(pdesc);
3767345b920SDoug MacEachern
3777345b920SDoug MacEachern    return SIGAR_OK;
3787345b920SDoug MacEachern}
3797345b920SDoug MacEachern
380dffe0da8SDoug MacEachernstatic int fileattrs_get(sigar_t *sigar,
381dffe0da8SDoug MacEachern                         const char *file,
382dffe0da8SDoug MacEachern                         sigar_file_attrs_t *fileattrs,
383dffe0da8SDoug MacEachern                         int linkinfo)
384dffe0da8SDoug MacEachern{
38531108707SDoug MacEachern    BY_HANDLE_FILE_INFORMATION info;
386dffe0da8SDoug MacEachern    WIN32_FILE_ATTRIBUTE_DATA attrs;
38731108707SDoug MacEachern    HANDLE handle;
38831108707SDoug MacEachern    DWORD flags;
389dffe0da8SDoug MacEachern
390dffe0da8SDoug MacEachern    SIGAR_ZERO(fileattrs);
391dffe0da8SDoug MacEachern
392dffe0da8SDoug MacEachern    if (!GetFileAttributesExA(file,
393dffe0da8SDoug MacEachern                              GetFileExInfoStandard,
394dffe0da8SDoug MacEachern                              &attrs))
395dffe0da8SDoug MacEachern    {
396dffe0da8SDoug MacEachern        return GetLastError();
397dffe0da8SDoug MacEachern    }
398dffe0da8SDoug MacEachern
399dffe0da8SDoug MacEachern    fillin_fileattrs(fileattrs, &attrs, linkinfo);
400dffe0da8SDoug MacEachern
40131108707SDoug MacEachern    flags = fileattrs->type == SIGAR_FILETYPE_DIR ?
40231108707SDoug MacEachern        FILE_FLAG_BACKUP_SEMANTICS :
40331108707SDoug MacEachern        FILE_ATTRIBUTE_NORMAL;
40431108707SDoug MacEachern
405f27542afSTrevor Pounds    /**
406f27542afSTrevor Pounds     * We need to set dwDesiredAccess to 0 to work in cases where GENERIC_READ can fail.
407f27542afSTrevor Pounds     *
408f27542afSTrevor Pounds     * see: http://msdn.microsoft.com/en-us/library/aa363858(VS.85).aspx
409f27542afSTrevor Pounds     */
41031108707SDoug MacEachern    handle = CreateFile(file,
411f27542afSTrevor Pounds                        0,
412f27542afSTrevor Pounds                        0,
41331108707SDoug MacEachern                        NULL,
41431108707SDoug MacEachern                        OPEN_EXISTING,
41531108707SDoug MacEachern                        flags,
41631108707SDoug MacEachern                        NULL);
41742d0b984STrond Norbye
41831108707SDoug MacEachern    if (handle != INVALID_HANDLE_VALUE) {
41931108707SDoug MacEachern        if (GetFileInformationByHandle(handle, &info)) {
42031108707SDoug MacEachern            fileattrs->inode =
421f854a40aSAliaksey Kandratsenka                (long long)info.nFileIndexLow |
422f854a40aSAliaksey Kandratsenka                ((long long)info.nFileIndexHigh << 32);
42331108707SDoug MacEachern            fileattrs->device = info.dwVolumeSerialNumber;
42431108707SDoug MacEachern            fileattrs->nlink  = info.nNumberOfLinks;
42531108707SDoug MacEachern        }
42631108707SDoug MacEachern        CloseHandle(handle);
42731108707SDoug MacEachern    }
42831108707SDoug MacEachern
4297345b920SDoug MacEachern    get_security_info(sigar, file, fileattrs);
4307345b920SDoug MacEachern
431dffe0da8SDoug MacEachern    return SIGAR_OK;
432dffe0da8SDoug MacEachern}
433dffe0da8SDoug MacEachern
434dffe0da8SDoug MacEachernSIGAR_DECLARE(int) sigar_file_attrs_get(sigar_t *sigar,
435dffe0da8SDoug MacEachern                                        const char *file,
436dffe0da8SDoug MacEachern                                        sigar_file_attrs_t *fileattrs)
437dffe0da8SDoug MacEachern{
438dffe0da8SDoug MacEachern    return fileattrs_get(sigar, file, fileattrs, 0);
439dffe0da8SDoug MacEachern}
440dffe0da8SDoug MacEachern
441dffe0da8SDoug MacEachernSIGAR_DECLARE(int) sigar_link_attrs_get(sigar_t *sigar,
442dffe0da8SDoug MacEachern                                        const char *file,
443dffe0da8SDoug MacEachern                                        sigar_file_attrs_t *fileattrs)
444dffe0da8SDoug MacEachern{
445dffe0da8SDoug MacEachern    return fileattrs_get(sigar, file, fileattrs, 1);
446dffe0da8SDoug MacEachern}
447dffe0da8SDoug MacEachern
448dffe0da8SDoug MacEachernstatic __inline int file_type(char *file)
449dffe0da8SDoug MacEachern{
450dffe0da8SDoug MacEachern    WIN32_FILE_ATTRIBUTE_DATA attrs;
451dffe0da8SDoug MacEachern
452dffe0da8SDoug MacEachern    if (!GetFileAttributesExA(file,
453dffe0da8SDoug MacEachern                              GetFileExInfoStandard,
454dffe0da8SDoug MacEachern                              &attrs))
455dffe0da8SDoug MacEachern    {
456dffe0da8SDoug MacEachern        return -1;
457dffe0da8SDoug MacEachern    }
458dffe0da8SDoug MacEachern
459dffe0da8SDoug MacEachern    if (attrs.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
460dffe0da8SDoug MacEachern        return SIGAR_FILETYPE_LNK;
461dffe0da8SDoug MacEachern    }
462dffe0da8SDoug MacEachern    else if (attrs.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
463dffe0da8SDoug MacEachern        return SIGAR_FILETYPE_DIR;
464dffe0da8SDoug MacEachern    }
465dffe0da8SDoug MacEachern    else {
466dffe0da8SDoug MacEachern        return SIGAR_FILETYPE_REG;
467dffe0da8SDoug MacEachern    }
468dffe0da8SDoug MacEachern}
469dffe0da8SDoug MacEachern
470e058d29cSDoug MacEachernstatic int dir_stat_get(sigar_t *sigar,
471e058d29cSDoug MacEachern                        const char *dir,
472e058d29cSDoug MacEachern                        sigar_dir_stat_t *dirstats,
473e058d29cSDoug MacEachern                        int recurse)
474dffe0da8SDoug MacEachern{
47519d9d3feSDoug MacEachern    int status;
476dffe0da8SDoug MacEachern    char name[SIGAR_PATH_MAX+1];
477dffe0da8SDoug MacEachern    int len = strlen(dir);
478dffe0da8SDoug MacEachern    int max = sizeof(name)-len-1;
479dffe0da8SDoug MacEachern    char *ptr = name;
480dffe0da8SDoug MacEachern    WIN32_FIND_DATA data;
481dffe0da8SDoug MacEachern    HANDLE handle;
482dffe0da8SDoug MacEachern    DWORD error;
483dffe0da8SDoug MacEachern    char delim;
484dffe0da8SDoug MacEachern
485dffe0da8SDoug MacEachern    if (file_type((char *)dir) != SIGAR_FILETYPE_DIR) {
486dffe0da8SDoug MacEachern        return ERROR_NO_MORE_FILES;
487dffe0da8SDoug MacEachern    }
488dffe0da8SDoug MacEachern
489dffe0da8SDoug MacEachern    strncpy(name, dir, sizeof(name));
490dffe0da8SDoug MacEachern    ptr += len;
491dffe0da8SDoug MacEachern    if (strchr(dir, '/')) {
492dffe0da8SDoug MacEachern        delim = '/';
493dffe0da8SDoug MacEachern    }
494dffe0da8SDoug MacEachern    else {
495dffe0da8SDoug MacEachern        delim = '\\';
496dffe0da8SDoug MacEachern    }
497dffe0da8SDoug MacEachern    if (name[len] != delim) {
498dffe0da8SDoug MacEachern        *ptr++ = delim;
499dffe0da8SDoug MacEachern        len++;
500dffe0da8SDoug MacEachern        max--;
501dffe0da8SDoug MacEachern    }
502dffe0da8SDoug MacEachern
503dffe0da8SDoug MacEachern    /* e.g. "C:\sigar\*" */
504dffe0da8SDoug MacEachern    name[len] = '*';
505dffe0da8SDoug MacEachern    name[len+1] = '\0';
506dffe0da8SDoug MacEachern
507dffe0da8SDoug MacEachern    handle = FindFirstFile(name, &data);
508dffe0da8SDoug MacEachern    if (handle == INVALID_HANDLE_VALUE) {
509dffe0da8SDoug MacEachern        return GetLastError();
510dffe0da8SDoug MacEachern    }
511dffe0da8SDoug MacEachern
512771742caSDoug MacEachern    do {
513dffe0da8SDoug MacEachern        /* skip '.' and '..' */
514dffe0da8SDoug MacEachern        if (IS_DOTDIR(data.cFileName)) {
515dffe0da8SDoug MacEachern            continue;
516dffe0da8SDoug MacEachern        }
517dffe0da8SDoug MacEachern
5183e84be00SDoug MacEachern        dirstats->disk_usage +=
5193e84be00SDoug MacEachern            (data.nFileSizeHigh * (MAXDWORD+1)) +
5203e84be00SDoug MacEachern            data.nFileSizeLow;
5213e84be00SDoug MacEachern
522dffe0da8SDoug MacEachern        /* e.g. "C:\sigar\lib" */
523dffe0da8SDoug MacEachern        strncpy(ptr, data.cFileName, max);
524dffe0da8SDoug MacEachern        ptr[max] = '\0';
525dffe0da8SDoug MacEachern
526dffe0da8SDoug MacEachern        switch (file_type(name)) {
527dffe0da8SDoug MacEachern          case -1:
528dffe0da8SDoug MacEachern            break;
529dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_REG:
530dffe0da8SDoug MacEachern            ++dirstats->files;
531dffe0da8SDoug MacEachern            break;
532dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_DIR:
533dffe0da8SDoug MacEachern            ++dirstats->subdirs;
53419d9d3feSDoug MacEachern            if (recurse) {
53542d0b984STrond Norbye                status =
53619d9d3feSDoug MacEachern                    dir_stat_get(sigar, name,
53719d9d3feSDoug MacEachern                                 dirstats, recurse);
53831dcf1bcSDoug MacEachern                if (status != SIGAR_OK) {
53919d9d3feSDoug MacEachern                    DIR_STAT_WARN();
54019d9d3feSDoug MacEachern                }
54119d9d3feSDoug MacEachern            }
542dffe0da8SDoug MacEachern            break;
543dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_LNK:
544dffe0da8SDoug MacEachern            ++dirstats->symlinks;
545dffe0da8SDoug MacEachern            break;
546dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_CHR:
547dffe0da8SDoug MacEachern            ++dirstats->chrdevs;
548dffe0da8SDoug MacEachern            break;
549dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_BLK:
550dffe0da8SDoug MacEachern            ++dirstats->blkdevs;
551dffe0da8SDoug MacEachern            break;
552dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_SOCK:
553dffe0da8SDoug MacEachern            ++dirstats->sockets;
554dffe0da8SDoug MacEachern            break;
555dffe0da8SDoug MacEachern          default:
556dffe0da8SDoug MacEachern            ++dirstats->total;
557dffe0da8SDoug MacEachern        }
558771742caSDoug MacEachern    } while (FindNextFile(handle, &data));
559dffe0da8SDoug MacEachern
560dffe0da8SDoug MacEachern    error = GetLastError();
561dffe0da8SDoug MacEachern
562dffe0da8SDoug MacEachern    FindClose(handle);
563dffe0da8SDoug MacEachern
564dffe0da8SDoug MacEachern    if (error != ERROR_NO_MORE_FILES) {
565dffe0da8SDoug MacEachern        return error;
566dffe0da8SDoug MacEachern    }
567dffe0da8SDoug MacEachern
56860be6b11SDoug MacEachern    dirstats->total =
569dffe0da8SDoug MacEachern        dirstats->files +
570dffe0da8SDoug MacEachern        dirstats->subdirs +
571dffe0da8SDoug MacEachern        dirstats->symlinks +
572dffe0da8SDoug MacEachern        dirstats->chrdevs +
573dffe0da8SDoug MacEachern        dirstats->blkdevs +
574dffe0da8SDoug MacEachern        dirstats->sockets;
575dffe0da8SDoug MacEachern
576dffe0da8SDoug MacEachern    return SIGAR_OK;
577dffe0da8SDoug MacEachern}
578dffe0da8SDoug MacEachern
579dffe0da8SDoug MacEachern#else
580dffe0da8SDoug MacEachern
581dffe0da8SDoug MacEachern#include <dirent.h>
582dffe0da8SDoug MacEachern#include <errno.h>
583dffe0da8SDoug MacEachern#include <sys/stat.h>
584dffe0da8SDoug MacEachern#include <sys/types.h>
585dffe0da8SDoug MacEachern
586dffe0da8SDoug MacEachernstatic sigar_file_type_e filetype_from_mode(mode_t mode)
587dffe0da8SDoug MacEachern{
588dffe0da8SDoug MacEachern    sigar_file_type_e type;
589dffe0da8SDoug MacEachern
590dffe0da8SDoug MacEachern    switch (mode & S_IFMT) {
591dffe0da8SDoug MacEachern    case S_IFREG:
592dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_REG;  break;
593dffe0da8SDoug MacEachern    case S_IFDIR:
594dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_DIR;  break;
595dffe0da8SDoug MacEachern    case S_IFLNK:
596dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_LNK;  break;
597dffe0da8SDoug MacEachern    case S_IFCHR:
598dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_CHR;  break;
599dffe0da8SDoug MacEachern    case S_IFBLK:
600dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_BLK;  break;
601dffe0da8SDoug MacEachern#if defined(S_IFFIFO)
602dffe0da8SDoug MacEachern    case S_IFFIFO:
603dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_PIPE; break;
604dffe0da8SDoug MacEachern#endif
605dffe0da8SDoug MacEachern#if !defined(BEOS) && defined(S_IFSOCK)
606dffe0da8SDoug MacEachern    case S_IFSOCK:
607dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_SOCK; break;
608dffe0da8SDoug MacEachern#endif
609dffe0da8SDoug MacEachern
610dffe0da8SDoug MacEachern    default:
61142d0b984STrond Norbye        /* Work around missing S_IFxxx values above
612dffe0da8SDoug MacEachern         * for Linux et al.
613dffe0da8SDoug MacEachern         */
614dffe0da8SDoug MacEachern#if !defined(S_IFFIFO) && defined(S_ISFIFO)
61542d0b984STrond Norbye        if (S_ISFIFO(mode)) {
616dffe0da8SDoug MacEachern            type = SIGAR_FILETYPE_PIPE;
61742d0b984STrond Norbye        } else
618dffe0da8SDoug MacEachern#endif
619dffe0da8SDoug MacEachern#if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK)
62042d0b984STrond Norbye        if (S_ISSOCK(mode)) {
621dffe0da8SDoug MacEachern            type = SIGAR_FILETYPE_SOCK;
62242d0b984STrond Norbye        } else
623dffe0da8SDoug MacEachern#endif
624dffe0da8SDoug MacEachern        type = SIGAR_FILETYPE_UNKFILE;
625dffe0da8SDoug MacEachern    }
626dffe0da8SDoug MacEachern    return type;
627dffe0da8SDoug MacEachern}
628dffe0da8SDoug MacEachern
629dffe0da8SDoug MacEachernstatic sigar_uint64_t sigar_unix_mode2perms(mode_t mode)
630dffe0da8SDoug MacEachern{
631dffe0da8SDoug MacEachern    sigar_uint64_t perms = 0;
632dffe0da8SDoug MacEachern
633dffe0da8SDoug MacEachern    if (mode & S_IRUSR)
634dffe0da8SDoug MacEachern        perms |= SIGAR_UREAD;
635dffe0da8SDoug MacEachern    if (mode & S_IWUSR)
636dffe0da8SDoug MacEachern        perms |= SIGAR_UWRITE;
637dffe0da8SDoug MacEachern    if (mode & S_IXUSR)
638dffe0da8SDoug MacEachern        perms |= SIGAR_UEXECUTE;
639dffe0da8SDoug MacEachern
640dffe0da8SDoug MacEachern    if (mode & S_IRGRP)
641dffe0da8SDoug MacEachern        perms |= SIGAR_GREAD;
642dffe0da8SDoug MacEachern    if (mode & S_IWGRP)
643dffe0da8SDoug MacEachern        perms |= SIGAR_GWRITE;
644dffe0da8SDoug MacEachern    if (mode & S_IXGRP)
645dffe0da8SDoug MacEachern        perms |= SIGAR_GEXECUTE;
646dffe0da8SDoug MacEachern
647dffe0da8SDoug MacEachern    if (mode & S_IROTH)
648dffe0da8SDoug MacEachern        perms |= SIGAR_WREAD;
649dffe0da8SDoug MacEachern    if (mode & S_IWOTH)
650dffe0da8SDoug MacEachern        perms |= SIGAR_WWRITE;
651dffe0da8SDoug MacEachern    if (mode & S_IXOTH)
652dffe0da8SDoug MacEachern        perms |= SIGAR_WEXECUTE;
653dffe0da8SDoug MacEachern
654dffe0da8SDoug MacEachern    return perms;
655dffe0da8SDoug MacEachern}
656dffe0da8SDoug MacEachern
657e69ec3d9SDoug MacEachernstatic void copy_stat_info(sigar_file_attrs_t *fileattrs,
658e69ec3d9SDoug MacEachern                           struct stat *info)
659dffe0da8SDoug MacEachern{
660dffe0da8SDoug MacEachern    fileattrs->permissions = sigar_unix_mode2perms(info->st_mode);
661dffe0da8SDoug MacEachern    fileattrs->type        = filetype_from_mode(info->st_mode);
662dffe0da8SDoug MacEachern    fileattrs->uid         = info->st_uid;
663dffe0da8SDoug MacEachern    fileattrs->gid         = info->st_gid;
664dffe0da8SDoug MacEachern    fileattrs->size        = info->st_size;
665dffe0da8SDoug MacEachern    fileattrs->inode       = info->st_ino;
666dffe0da8SDoug MacEachern    fileattrs->device      = info->st_dev;
667dffe0da8SDoug MacEachern    fileattrs->nlink       = info->st_nlink;
668dffe0da8SDoug MacEachern    fileattrs->atime       = info->st_atime;
669dffe0da8SDoug MacEachern    fileattrs->mtime       = info->st_mtime;
670dffe0da8SDoug MacEachern    fileattrs->ctime       = info->st_ctime;
671dffe0da8SDoug MacEachern    fileattrs->atime *= 1000;
672dffe0da8SDoug MacEachern    fileattrs->mtime *= 1000;
673dffe0da8SDoug MacEachern    fileattrs->ctime *= 1000;
674dffe0da8SDoug MacEachern}
675dffe0da8SDoug MacEachern
676dffe0da8SDoug MacEachernint sigar_file_attrs_get(sigar_t *sigar,
677dffe0da8SDoug MacEachern                         const char *file,
678dffe0da8SDoug MacEachern                         sigar_file_attrs_t *fileattrs)
679dffe0da8SDoug MacEachern{
680dffe0da8SDoug MacEachern    struct stat info;
681dffe0da8SDoug MacEachern
682dffe0da8SDoug MacEachern    if (stat(file, &info) == 0) {
683dffe0da8SDoug MacEachern        copy_stat_info(fileattrs, &info);
684dffe0da8SDoug MacEachern        return SIGAR_OK;
685dffe0da8SDoug MacEachern    }
686dffe0da8SDoug MacEachern    else {
687dffe0da8SDoug MacEachern        return errno;
688dffe0da8SDoug MacEachern    }
689dffe0da8SDoug MacEachern}
690dffe0da8SDoug MacEachern
691dffe0da8SDoug MacEachernint sigar_link_attrs_get(sigar_t *sigar,
692dffe0da8SDoug MacEachern                         const char *file,
693dffe0da8SDoug MacEachern                         sigar_file_attrs_t *fileattrs)
694dffe0da8SDoug MacEachern{
695dffe0da8SDoug MacEachern    struct stat info;
696dffe0da8SDoug MacEachern
697dffe0da8SDoug MacEachern    if (lstat(file, &info) == 0) {
698dffe0da8SDoug MacEachern        copy_stat_info(fileattrs, &info);
699dffe0da8SDoug MacEachern        return SIGAR_OK;
700dffe0da8SDoug MacEachern    }
701dffe0da8SDoug MacEachern    else {
702dffe0da8SDoug MacEachern        return errno;
703dffe0da8SDoug MacEachern    }
704dffe0da8SDoug MacEachern}
705dffe0da8SDoug MacEachern
7067eb82863SDoug MacEachernstatic int dir_stat_get(sigar_t *sigar,
7077eb82863SDoug MacEachern                        const char *dir,
7086f6f92fbSDoug MacEachern                        sigar_dir_stat_t *dirstats,
7096f6f92fbSDoug MacEachern                        int recurse)
710dffe0da8SDoug MacEachern{
7116f6f92fbSDoug MacEachern    int status;
712dffe0da8SDoug MacEachern    char name[SIGAR_PATH_MAX+1];
713dffe0da8SDoug MacEachern    int len = strlen(dir);
714dffe0da8SDoug MacEachern    int max = sizeof(name)-len-1;
715dffe0da8SDoug MacEachern    char *ptr = name;
716dffe0da8SDoug MacEachern    DIR *dirp = opendir(dir);
717dffe0da8SDoug MacEachern    struct dirent *ent;
718dffe0da8SDoug MacEachern    struct stat info;
719dffe0da8SDoug MacEachern#ifdef HAVE_READDIR_R
720dffe0da8SDoug MacEachern    struct dirent dbuf;
721dffe0da8SDoug MacEachern#endif
722dffe0da8SDoug MacEachern
723dffe0da8SDoug MacEachern    if (!dirp) {
724dffe0da8SDoug MacEachern        return errno;
725dffe0da8SDoug MacEachern    }
726dffe0da8SDoug MacEachern
727dffe0da8SDoug MacEachern    strncpy(name, dir, sizeof(name));
728dffe0da8SDoug MacEachern    ptr += len;
729dffe0da8SDoug MacEachern    if (name[len] != '/') {
730dffe0da8SDoug MacEachern        *ptr++ = '/';
731dffe0da8SDoug MacEachern        len++;
732dffe0da8SDoug MacEachern        max--;
733dffe0da8SDoug MacEachern    }
734dffe0da8SDoug MacEachern
735dffe0da8SDoug MacEachern#ifdef HAVE_READDIR_R
736dffe0da8SDoug MacEachern    while (readdir_r(dirp, &dbuf, &ent) == 0) {
737dffe0da8SDoug MacEachern        if (ent == NULL) {
738dffe0da8SDoug MacEachern            break;
739dffe0da8SDoug MacEachern        }
740dffe0da8SDoug MacEachern#else
741dffe0da8SDoug MacEachern    while ((ent = readdir(dirp))) {
742dffe0da8SDoug MacEachern#endif
743dffe0da8SDoug MacEachern        /* skip '.' and '..' */
744dffe0da8SDoug MacEachern        if (IS_DOTDIR(ent->d_name)) {
745dffe0da8SDoug MacEachern            continue;
746dffe0da8SDoug MacEachern        }
747dffe0da8SDoug MacEachern
748dffe0da8SDoug MacEachern        strncpy(ptr, ent->d_name, max);
749dffe0da8SDoug MacEachern        ptr[max] = '\0';
750dffe0da8SDoug MacEachern
751dffe0da8SDoug MacEachern        if (lstat(name, &info) != 0) {
752dffe0da8SDoug MacEachern            continue;
753dffe0da8SDoug MacEachern        }
754dffe0da8SDoug MacEachern
755ab3abd51SDoug MacEachern        dirstats->disk_usage += info.st_size;
756ab3abd51SDoug MacEachern
757dffe0da8SDoug MacEachern        switch (filetype_from_mode(info.st_mode)) {
758dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_REG:
759dffe0da8SDoug MacEachern            ++dirstats->files;
760dffe0da8SDoug MacEachern            break;
761dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_DIR:
762dffe0da8SDoug MacEachern            ++dirstats->subdirs;
7636f6f92fbSDoug MacEachern            if (recurse) {
76442d0b984STrond Norbye                status =
7656f6f92fbSDoug MacEachern                    dir_stat_get(sigar, name,
7666f6f92fbSDoug MacEachern                                 dirstats, recurse);
767e69ec3d9SDoug MacEachern                if (status != SIGAR_OK) {
768f8060d5cSDoug MacEachern                    DIR_STAT_WARN();
7696f6f92fbSDoug MacEachern                }
7706f6f92fbSDoug MacEachern            }
771dffe0da8SDoug MacEachern            break;
772dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_LNK:
773dffe0da8SDoug MacEachern            ++dirstats->symlinks;
774dffe0da8SDoug MacEachern            break;
775dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_CHR:
776dffe0da8SDoug MacEachern            ++dirstats->chrdevs;
777dffe0da8SDoug MacEachern            break;
778dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_BLK:
779dffe0da8SDoug MacEachern            ++dirstats->blkdevs;
780dffe0da8SDoug MacEachern            break;
781dffe0da8SDoug MacEachern          case SIGAR_FILETYPE_SOCK:
782dffe0da8SDoug MacEachern            ++dirstats->sockets;
783dffe0da8SDoug MacEachern            break;
784dffe0da8SDoug MacEachern          default:
785dffe0da8SDoug MacEachern            ++dirstats->total;
786dffe0da8SDoug MacEachern        }
787dffe0da8SDoug MacEachern    }
788dffe0da8SDoug MacEachern
78960be6b11SDoug MacEachern    dirstats->total =
790dffe0da8SDoug MacEachern        dirstats->files +
791dffe0da8SDoug MacEachern        dirstats->subdirs +
792dffe0da8SDoug MacEachern        dirstats->symlinks +
793dffe0da8SDoug MacEachern        dirstats->chrdevs +
794dffe0da8SDoug MacEachern        dirstats->blkdevs +
795dffe0da8SDoug MacEachern        dirstats->sockets;
796dffe0da8SDoug MacEachern
797dffe0da8SDoug MacEachern    closedir(dirp);
798dffe0da8SDoug MacEachern
799dffe0da8SDoug MacEachern    return SIGAR_OK;
800dffe0da8SDoug MacEachern}
801dffe0da8SDoug MacEachern
802d695f3deSDoug MacEachern#endif
803d695f3deSDoug MacEachern
804d695f3deSDoug MacEachernSIGAR_DECLARE(int) sigar_dir_stat_get(sigar_t *sigar,
805d695f3deSDoug MacEachern                                      const char *dir,
806d695f3deSDoug MacEachern                                      sigar_dir_stat_t *dirstats)
8077eb82863SDoug MacEachern{
808e058d29cSDoug MacEachern    SIGAR_ZERO(dirstats);
8096f6f92fbSDoug MacEachern    return dir_stat_get(sigar, dir, dirstats, 0);
8107eb82863SDoug MacEachern}
811d50e4efeSDoug MacEachern
812d50e4efeSDoug MacEachernSIGAR_DECLARE(int) sigar_dir_usage_get(sigar_t *sigar,
813d50e4efeSDoug MacEachern                                       const char *dir,
814d50e4efeSDoug MacEachern                                       sigar_dir_usage_t *dirusage)
815d50e4efeSDoug MacEachern{
816d50e4efeSDoug MacEachern    SIGAR_ZERO(dirusage);
817d50e4efeSDoug MacEachern    return dir_stat_get(sigar, dir, dirusage, 1);
818d50e4efeSDoug MacEachern}
819