LINUX.ORG.RU

Неверное значение equery size ?

 , , ,


0

3

Привет.

В свободное время потихоньку пилю свои велосипеды для gentoo. Дошёл черёд equery, а в частности equery size.

[cppmm@damned mportage]$ equery s bash -b
 * app-shells/bash-5.1_p16-r2
         Total files : 45
         Total size  : 2889615

Проверяем. Для проверки я смотрю в CONTENTS, достаю оттуда только то, что является по типу obj и суммирую:

foreach my $line (<$contents_handle>) {
  my @line = split / /, $line;
  $files++;
  if ($line[0] eq 'obj') {
    my $file_size = (stat $line[1])[7];
    $size = $size + $file_size if defined($file_size);
  }
}
В итоге получаю: 2602878 Ну, предположим, perl врёт. Посчитаем bash'ем(однострочник одноразовый на скорую руку).
for size in $(ls -l $(grep -E '^obj' CONTENTS | awk '{print $2}') | awk '{print $5}') ; do let "FSIZE = FSIZE + $size" ; echo $FSIZE ; done ; unset FSIZE
Получается, perl всё правильно посчитал: 2602878

Иду смотреть в код gentoolkit

        seen = set()
        size = n_files = n_uncounted = 0
        for path in self.parsed_contents(prefix_root=True):
            try:
                st = os.lstat(_unicode_encode(path, encoding=_encodings["fs"]))
            except OSError:
                continue

            # Remove hardlinks by checking for duplicate inodes. Bug #301026.
            file_inode = st.st_ino
            if file_inode in seen:
                continue
            seen.add(file_inode)

            try:
                size += st.st_size
                n_files += 1
            except OSError:
                n_uncounted += 1

        return (size, n_files, n_uncounted)

За исключением дополнительной проверки на хардлинки(в bash'е, взятом для примера, хардлинков нет), всё выглядит так же, как у меня. Но почему тогда итоговая сумма различается? Где я просчитался и откуда equery берёт ещё почти три сотни килобайт?

Содержание CONTENTS:

dir /usr
dir /usr/share
dir /usr/share/info
sym /usr/share/info/bashref.info.bz2 -> bash.info.bz2 1673668093
obj /usr/share/info/bash.info.bz2 393a14a5ef4f7a9fd1f972fe722e1b4c 1673668089
dir /usr/share/man
dir /usr/share/man/man1
obj /usr/share/man/man1/rbash.1.bz2 7d8fa9646b44685ce5b435251a755669 1673668091
obj /usr/share/man/man1/bash.1.bz2 89a2fe46e383d7f6bf247d8f8dfeb2d0 1673668089
obj /usr/share/man/man1/bashbug.1.bz2 9d12dc1958d8e640264182b801e24316 1673668089
obj /usr/share/man/man1/bash_builtins.1.bz2 e84268f4670be0fa8ed185a43ca1d233 1673668091
dir /usr/share/doc
dir /usr/share/doc/bash-5.1_p16-r2
obj /usr/share/doc/bash-5.1_p16-r2/CHANGES.bz2 5c43139aae5703fe86c394c3e45b66ea 1673668090
obj /usr/share/doc/bash-5.1_p16-r2/POSIX.bz2 e641b4188c5824c1441b97b594da69ac 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/NEWS.bz2 6c47111c691f28fdf8822ae2c16b7536 1673668090
obj /usr/share/doc/bash-5.1_p16-r2/RBASH.bz2 ed3e9e7fe6ce0e83d05cfb994e0cecdb 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/INTRO.bz2 0adb1e98d3ad2a3a012d696ea17e5547 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/COMPAT.bz2 7029427047217c824828bf2fa4c3816f 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/AUTHORS.bz2 65f88febe33195919919139655121a7f 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/FAQ.bz2 c54d1bdf18849c74a94d5dcebce4e623 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/README.bz2 a9ebdee593521b64c96fad5bb7b3a3c3 1673668089
dir /usr/share/doc/bash-5.1_p16-r2/html
obj /usr/share/doc/bash-5.1_p16-r2/html/bashref.html b0bf8f6881f88d1fd2aff973ae1975af 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/html/bash.html c9336f41ad159aa7d606a1999d75e020 1673668089
obj /usr/share/doc/bash-5.1_p16-r2/ChangeLog.bz2 83aeece17d29263f5ff312228c1e71ca 1673668091
dir /usr/share/locale
dir /usr/share/locale/ru
dir /usr/share/locale/ru/LC_MESSAGES
obj /usr/share/locale/ru/LC_MESSAGES/bash.mo 39c19d7b6487b5108893f42bf2a74638 1673668089
dir /usr/bin
obj /usr/bin/bashbug 53b7bde997005b1c10aa3d182111b397 1673668089
dir /etc
dir /etc/bash
obj /etc/bash/bash_logout 229ccc2980a94877f2e87f957e9da7bf 1673668090
obj /etc/bash/bashrc 4ba9eb2e8e8e5a503477a6445a11200c 1673668091
dir /etc/bash/bashrc.d
obj /etc/bash/bashrc.d/.keep_app-shells_bash-0 d41d8cd98f00b204e9800998ecf8427e 1673668090
dir /etc/skel
obj /etc/skel/.bash_logout 7d8a8ef90c1818a0cd66808ac2740638 1673668091
obj /etc/skel/.bash_profile d3322040528c46743ea8e4b0b9a186bc 1673668091
obj /etc/skel/.bashrc d210b9cd7fc07420736480f2062d7d7f 1673668091
dir /bin
sym /bin/rbash -> bash 1673668090
obj /bin/bash 7e6a211d8a6e4a14b8c8ffbc49a38fcd 1673668093

Я в код gentoolkit глубоко не смотрел, но не может быть такого, что equery считает также размер самой директории в дополнении к размеру файлов в ней:

Ну потому что банальное:

oas1 ~ # mkdir 1
oas1 ~ # stat 1 | head -2
  Файл: 1
  Размер: 0             Блоков: 0          Блок В/В: 4096   каталог

выполненное на btrfs например будет несколько отличаться от такого же выполненного на ext4:

oas1 ~ # cd /backup
oas1 /backup # mkdir 1
oas1 /backup # stat 1 | head -2
  Файл: 1
  Размер: 4096          Блоков: 8          Блок В/В: 4096   каталог

Update: более того, я что-то не вижу исключений симлинков и директорий в методе getcontents здесь. Да, обрабатываются они несколько по разному, но на вход в size() для gentoolkit подаётся всё

Pinkbyte ★★★★★
()
Последнее исправление: Pinkbyte (всего исправлений: 2)

Ладно размер, у меня на одном компе при обновлении до xz-utils-5.4 почему-то распаковка этого типа архивов перестала работать. Из-за чего часть пакетов он не мог обновить потому, что не мог распаковать.

Правда при включении компа сегодня, почему-то запустилась проверка раздела на ошибки. Возможно аппаратная проблема или кабель - бывает время от времени :( При установке предыдущей версии 5.2.10 всё снова работает.

grem ★★★★★
()
Ответ на: комментарий от Pinkbyte

Спасибо.

Да, действительно, директории на ext4 тоже занимают место, я об этом не подумал. Поправил скрипт так, чтобы учитывало их тоже. Сумма стала больше похожа на правду. Осталась непонятная разница в 17 байт. :) Это для bash.

По другим пакетам - некоторые совпадают, а некоторые выдают и вовсе странный результат. Например, gcc.

[cppmm@damned mportage]$ equery s gcc -b
 * sys-devel/gcc-11.3.1_p20221209
         Total files : 1683
         Total size  : 198959950
[cppmm@damned mportage]$ ./mequery.pl -a size -n gcc
 * sys-devel/gcc-11.3.1_p20221209
         Total files : 1687
         Total size  : 200299405
[root@damned gcc-11.3.1_p20221209]$ wc -l CONTENTS 
1687 CONTENTS
Непонятно, почему equery насчитал меньше файлов, чем указано в CONTENTS и соответственно выдал меньший размер. Здесь уж точно выглядит ошибкой. Надо, видимо, всё-таки глубже залазить во внутренности gentoolkit.

shell-script ★★★★★
() автор топика
Ответ на: комментарий от grem

хе, выяснилось, что ошибка была связана с тем, что я для своего intel i3 550 использую -march=wesmere, но i3, в частности, не поддерживают pclmul из этого набора инструкций: https://wiki.gentoo.org/wiki/Safe_CFLAGS

Поэтому просто добавил -mno-pclmul и новая версия заработала.

grem ★★★★★
()
Ответ на: комментарий от shell-script

Сам удивился (нашёл баг похожий у человека с мобильным i3 той же архитектуры), наверное ничего другое подобные инструкции не использовало. Даже предыдущая версия работает. Но в новой они что-то меняли заметно.

grem ★★★★★
()
Последнее исправление: grem (всего исправлений: 2)
Ответ на: комментарий от Pinkbyte

Разобрался.

Действительно, нужно брать список всех файлов без исключений. А далее

  • Считать размеры непосредственно директорий.
  • Считать размеры непосредственно симлинков(не разыменовывать симлинк, а считать именно его размер - на ext4, к примеру, размер симлинка равен количеству байт в названии файла, на который ссылается симлинк).
  • Считать размеры самих файлов.
  • Исключить из подсчёта хардлинки.

Итого, на perl, если интересно, это будет выглядеть вот так:

my $files = 0;
my $size = 0;
my @inodes;
foreach my $line (<$contents_handle>) {
        my @line = split / /, $line;
        chomp $line[1];
        my @file_stat = lstat $line[1];
        if ( grep { $file_stat[1] eq $_ } @inodes ) {
                next;
        } else {
                push @inodes, $file_stat[1];
                $files++;
        }
        $size = $size + $file_stat[7] if defined($file_stat[7]);
}
Итого:
[cppmm@damned mportage]$ equery size -b git
 * dev-vcs/git-2.38.2
         Total files : 640
         Total size  : 26380025
[cppmm@damned mportage]$ ./mequery.pl -a size -n git
 * dev-vcs/git-2.38.2
         Total files : 640
         Total size  : 26380025
[cppmm@damned mportage]$ equery size -b gcc
 * sys-devel/gcc-11.3.1_p20221209
         Total files : 1683
         Total size  : 198959950
[cppmm@damned mportage]$ ./mequery.pl -a size -n gcc
 * sys-devel/gcc-11.3.1_p20221209
         Total files : 1683
         Total size  : 198959950
Спасибо за то, что дал направление, куда копать.

shell-script ★★★★★
() автор топика