Написание простой дю клон. Получение случайных значений для размеров файлов в подкаталогах. - PullRequest
3 голосов
/ 31 декабря 2011

Я пытаюсь написать базовую программу, которая суммирует размеры файлов всех файлов в текущем каталоге и всех подкаталогах.Я думал, что это будет хорошее упражнение.Я пытаюсь использовать базовую рекурсию для этого.Вот что у меня есть:

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <string.h>

long totalbytes = 0;

long dirsize(const char* directory, int verbose)
{
  struct dirent *de;
  struct stat s;
  DIR * dir; 
  //long total_items = 0;
  long filesize = 0;

  dir = opendir(directory);
  if (dir == NULL)
  {
     printf("Failed to open %s.\n", directory);
     return -1;
  }

  while ((de = readdir (dir)) != NULL)
  {
    stat(de->d_name, &s);
  if (S_ISLNK(s.st_mode)) 
  {
    printf("links are ignored.\n");
  }
  if (de->d_type == DT_REG)
  {
    filesize = 0; //be sure to reset this each time to avoid inaccuracy
    stat(de->d_name, &s); // get file info into our s structure
    if (verbose) 
    {
      printf("%s/%s : %ld bytes (%f MB)\n", directory, de->d_name, s.st_size, (float) s.st_size / 1024 / 1024);
    }
    filesize = s.st_size; //put file size into filesize variable
    totalbytes += filesize; //increment totalbytes
  }
  if (de->d_type == DT_DIR && strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0)
  {
    char pathname[PATH_MAX];
    sprintf(pathname, "%s/%s", directory, de->d_name);
    dirsize(pathname, verbose); //recursion: keep looping until no more subdirs remain
    }
  }
  closedir(dir);
  return totalbytes;
}

long compute_size(const char* directory, int verbose)
{
  long space = dirsize(directory, verbose);
  return space;
}

int main(int argc, char* argv[])
{
  if (argc != 2)
  {
    printf("Usage: dirsize DIRECTORY\n");
return -1;
  }

  int verbose = 1; //show or hide individual computations

  long space = compute_size(argv[1], verbose);
  if (space != -1)
  {
    float space_mb = (float) space / 1024 / 1024;
    printf("space occupied: %ld bytes\n", space);
    printf("(%f MB)\n", space_mb);
  }
  return 0;
}

Вот выходные данные моей программы (я также включаю ls из подкаталога)

08:35 PM@~/tmp$ ./dirsize .
./dirsize : 8369 bytes (0.007981 MB)
./diskstat.c : 1430 bytes (0.001364 MB)
./diskstat : 7993 bytes (0.007623 MB)
./ftw.c : 491 bytes (0.000468 MB)
./a.out : 8044 bytes (0.007671 MB)
./arrays.sh : 212 bytes (0.000202 MB)
./fileread/timestamp : 0 bytes (0.000000 MB)
./fileread/timestamp.c : 0 bytes (0.000000 MB)
./fileread/a.out : 8044 bytes (0.007671 MB)
./fileread/build.prop : 8044 bytes (0.007671 MB)
./fileread/read.c : 4096 bytes (0.003906 MB)
./fileread/read : 454656 bytes (0.433594 MB)
./local.fstab : 76 bytes (0.000072 MB)
./dirsize.c : 1857 bytes (0.001771 MB)
./echo.sh : 223 bytes (0.000213 MB)
./TEAMS.sh : 605 bytes (0.000577 MB)
space occupied: 504140 bytes
(0.480785 MB)
08:35 PM@~/tmp$ ls -l fileread/
total 40
-rwxr-xr-x 1 raidzero raidzero 8132 Dec 28 10:39 a.out
-rw-r--r-- 1 raidzero raidzero 2346 Dec 28 10:09 build.prop
-rwxr-xr-x 1 raidzero raidzero 8384 Dec 29 13:57 read
-rw-r--r-- 1 raidzero raidzero 1150 Dec 28 10:16 read.c
-rwxr-xr-x 1 raidzero raidzero 8132 Dec 29 13:57 timestamp
-rw-r--r-- 1 raidzero raidzero  659 Dec 28 10:39 timestamp.c
08:35 PM@~/tmp$

В моем ограниченном опыте, получение случайных данныхявляется признаком неправильного распределения памяти, но st_size в структуре stat является длинным int ..?

1 Ответ

2 голосов
/ 31 декабря 2011

de->d_name имеет только имя файла - оно не содержит пути, ведущего к нему. Например, вы набираете ./timestamp, а не ./fileread/timestamp. Вы можете либо создать полный путь к файлу, использовать chdir() для ввода каталогов по мере необходимости (небезопасно, если вы находитесь в многопоточной среде, и может быть хрупким, если каталоги перемещаются, когда вы в них - fchdir() может быть очень полезно, чтобы вернуться к более высоким каталогам), или (в недавних версиях Unixen) использовать функции openat() / fstat() для каталоги хода.

Обратите внимание, что, если бы вы проверили наличие ошибок из stat, вы бы заметили это. Всегда проверяйте эти сообщения об ошибках.

...