133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root/* 233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * 333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * Copyright (C) 2008, The Android Open Source Project 433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * 533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 633b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * you may not use this file except in compliance with the License. 733b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * You may obtain a copy of the License at 833b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * 933b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * http://www.apache.org/licenses/LICENSE-2.0 1033b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * 1133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * Unless required by applicable law or agreed to in writing, software 1233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 1333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * See the License for the specific language governing permissions and 1533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root * limitations under the License. 1633b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root */ 1733b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 1833b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root#include <dirent.h> 1933b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root#include <fcntl.h> 2033b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root#include <sys/stat.h> 2133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 2233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root#include <diskusage/dirsize.h> 2333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 2433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Rootint64_t stat_size(struct stat *s) 2533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root{ 2633b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root int64_t blksize = s->st_blksize; 2733b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root int64_t size = s->st_size; 2833b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 2933b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if (blksize) { 3033b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root /* round up to filesystem block size */ 3133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root size = (size + blksize - 1) & (~(blksize - 1)); 3233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } 3333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 3433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root return size; 3533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root} 3633b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 3733b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Rootint64_t calculate_dir_size(int dfd) 3833b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root{ 3933b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root int64_t size = 0; 4033b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root struct stat s; 4133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root DIR *d; 4233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root struct dirent *de; 4333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 4433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root d = fdopendir(dfd); 4533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if (d == NULL) { 4633b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root close(dfd); 4733b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root return 0; 4833b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } 4933b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 5033b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root while ((de = readdir(d))) { 5133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root const char *name = de->d_name; 5233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if (de->d_type == DT_DIR) { 5333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root int subfd; 5433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 5533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root /* always skip "." and ".." */ 5633b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if (name[0] == '.') { 5733b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if (name[1] == 0) 5833b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root continue; 5933b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if ((name[1] == '.') && (name[2] == 0)) 6033b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root continue; 6133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } 6233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root 6333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY); 6433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if (subfd >= 0) { 6533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root size += calculate_dir_size(subfd); 6633b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } 6733b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } else { 6833b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) { 6933b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root size += stat_size(&s); 7033b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } 7133b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } 7233b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root } 7333b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root closedir(d); 7433b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root return size; 7533b2264ea9ab0f1980c49698729a0ab3c51d07feKenny Root} 76