1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677 |
- /*
- *
- * Copyright (C) 2008, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <dirent.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <diskusage/dirsize.h>
- int64_t stat_size(struct stat *s)
- {
- int64_t blksize = s->st_blksize;
- // count actual blocks used instead of nominal file size
- int64_t size = s->st_blocks * 512;
- if (blksize) {
- /* round up to filesystem block size */
- size = (size + blksize - 1) & (~(blksize - 1));
- }
- return size;
- }
- int64_t calculate_dir_size(int dfd)
- {
- int64_t size = 0;
- struct stat s;
- DIR *d;
- struct dirent *de;
- d = fdopendir(dfd);
- if (d == NULL) {
- close(dfd);
- return 0;
- }
- while ((de = readdir(d))) {
- const char *name = de->d_name;
- if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
- size += stat_size(&s);
- }
- if (de->d_type == DT_DIR) {
- int subfd;
- /* always skip "." and ".." */
- if (name[0] == '.') {
- if (name[1] == 0)
- continue;
- if ((name[1] == '.') && (name[2] == 0))
- continue;
- }
- subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
- if (subfd >= 0) {
- size += calculate_dir_size(subfd);
- }
- }
- }
- closedir(d);
- return size;
- }
|