Portál AbcLinuxu, 25. dubna 2024 02:57

Jak je to s časem vzniku souboru na GNU Linux distribucích

17.2.2019 19:39 | Přečteno: 7549× | Výběrový blog

Zarazilo vás někdy, že příkaz stat(1) z GNU Coreutils na Linuxu vypisuje kromě klasické trojice unixových časových značek access, modify a change navíc také jakési birth, u kterého ale hodnota chybí? Co tu vůbec to prázdné birth dělá? Zajímat o tuto málo známou časovou značku jsem se začal až před pár měsíci při debugování jednoho problému, kdy jsem se snažil chytil čeho se dalo. A i když mi to nakonec přímo nepomohlo, postupně jsem se začal nořit do její historie a budoucnosti, takže tento zápisek je někde na pomezí softwarové archeologie a jaderných novinek, a mj. se v něm dozvíte, kde se tato časová značka vzala, jak s ní dnes na GNU Linuxových distribucích pracovat a jak to s ní vypadá do budoucna.

Pro lepší představu o čem tu píšu. Na následující ukázce je stat zavolaný na souboru uloženém na etx4. To vše na Fedoře 29, s GNU Coreutils 8.30 a jádrem 4.19.8:

$ stat public_html
  File: public_html
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: fd07h/64775d    Inode: 7341469     Links: 2
Access: (0755/drwxr-xr-x)  Uid: ( 1000/  martin)   Gid: ( 1000/  martin)
Context: unconfined_u:object_r:httpd_user_content_t:s0
Access: 2018-12-09 12:59:16.321622899 +0100
Modify: 2018-05-19 21:35:13.813112882 +0200
Change: 2018-12-09 02:51:38.961313721 +0100
 Birth: -
$

Souborové časové značky na Unixových systémech

Unixové souborové časové značky, jak je vrací systémové volání stat, jsou standardizované v normě POSIX takto:

Časová značka Položka v struct stat Význam
access st_atim poslední přístup k datům souboru
modify st_mtim poslední změna dat souboru
change st_ctim poslední změna statusu souboru (inode)

To, že se položka pro access time ve struktuře stat aktuálně jmenuje st_atim je dáno tím, že v ní je čas počítaný na nanosekundy, zatímco původní a dnes už zastaralé st_atime počítá čas se sekundovou přesností a je udržováno kvůli zpětné kompatibilitě. V Linuxu je tohle implementováno už od verze 2.5.48, viz stat(2). Dál v textu budu místo access time psát prostě atime, místo modify time mtime a pod, bez ohledu na rozdíl mezi st_atim a st_atime.

Z pohledu tohoto zápisku je ale důležitější a na první pohled nápadné to, že čas vzniku souboru tu nenajdeme.

Přitom pokud si někdo unixem nezasažený zběžně prohlédne jména časových značek v struktuře stat (viz tabulka výše), mohl by si myslet, že čas vzniku souboru podporovaný je a že ctime je asi zkratka pro creation time. Další studium man stránky by ale tento omyl rychle vyvrátilo. Podobně pokud si dnes přečtete článek The UNIX Time-Sharing System od tvůrců Unixu z roku 1973, mohlo by vás napadnout, že ctime opravu původně vznik souboru reprezentovalo aby se jeho význam později změnil, protože v tomto článku se mimo jiné píše:

The entry found thereby (the file’s i-node) contains the description of the file: … time of creation, last use, and last modification

Nicméně jak upozorňuje wikipedie, to by byl opět omyl. Několik prvních verzí tzv. Research Unixu sice čas vzniku souboru skutečně podporovalo, jak se můžeme přesvědčit např. v man stránce pro stat(2) z verze 3 z února roku 1973:

NAME            stat  --  get file status

SYNOPSIS        sys stat; name; buf  / stat = 18.

DESCRIPTION     name  points to a null-terminated string naming a
file; buf is the address of a 34(10) byte buffer into  which  in-
formation  is  placed  concerning the file.  It is unnecessary to
have any permissions at all with respect to the file, but all di-
rectories leading to the file must be readable.

After stat, buf has the following format:

buf, +1         i-number
+2,+3           flags (see below)
+4              number of links
+5              user ID of owner
+6,+7           size in bytes
+8,+9           first indirect block or contents block
+22,+23         eighth indirect block or contents block
+24,+25,+26,+27 creation time
+28,+29,+30,+31 modification time
+32,+33         unused

Btw zajímavé taky je, že příkaz stat z téže verze creation time neuvádí, tedy aspoň dle man stránky stat(1), zdroják se mi nepodařilo dohledat:

NAME            stat  --  get file status

SYNOPSIS        stat name1 ...

DESCRIPTION     stat gives several kinds of information about one
or more files:

   i-number
   access mode
   number of links
   owner
   size in bytes
   date and time of last modification
   name (useful when several files are named)

Ale hned v další verzi (Research) Unixu, tj. verzi 4 z listopadu 1973, již čas vzniku souboru nenajdeme. Za povšimnutí stojí, že V4 byla první verze Unixu napsaná v céčku. Díky tomu tak byly (mimo jiné) poprvé zavedeny názvy položek ve struktuře stat, které se ale trochu liší od dnes používaných. Viz opět manstránka stat(2) z V4:

stat  get file status (stat = 18.)
sys stat; name; buf stat(name, buf)
char *name;
struct  inode  *buf;  points to a null-terminated string naming a
file; is the address of a 36(10) byte buffer into which  informa-
tion  is  placed  concerning the file.  It is unnecessary to have
any permissions at all with respect to the file, but all directo-
ries leading to the file must be readable.  After has the follow-
ing structure (starting offset given in bytes):
struct {
   char  minor;         /* +0: minor device of i-node */
   char  major;         /* +1: major device */
   int   inumber        /* +2 */
   int   flags;         /* +4: see below */
   char  nlinks;        /* +6: number of links to file */
   char  uid;           /* +7: user ID of owner */
   char  gid;           /* +8: group ID of owner */
   char  size0;         /* +9: high byte of 24-bit size */
   int   size1;         /* +10: low word of 24-bit size */
   int   addr[8];       /* +12: block numbers or device number */
   int   actime[2];     /* +28: time of last access */
   int   modtime[2];    /* +32: time of last modification */
};

Časová značka ctime se pak poprvé objevila až ve verzi 7 z ledna 1979, a to hned v dnešním významu change time, takže ctime opravdu creation time nikdy neznamenalo:

struct  stat
{
    dev_t   st_dev;
    ino_t   st_ino;
    unsigned short st_mode;
    short   st_nlink;
    short   st_uid;
    short   st_gid;
    dev_t   st_rdev;
    off_t   st_size;
    time_t  st_atime;
    time_t  st_mtime;
    time_t  st_ctime;
};

V této podobě pak časové značky ze struktury stat vydržely až do POSIX standardu a dnešních dní (tedy až na ten výše zmiňovaný detail s nanosekundovou přesností).

<hint> Nějakou dobu se mi pletlo, jaký je rozdíl mezi mtime (modify) a ctime (change) a např. při hledání souborů podle data jsem si to musel čas od času dohledávat. Na základě informací z předchozího textu se ale nabízí pomůcka pro zapamatování rozdílu: ctime je timestamp, co se lidem občas plete s creation time a co nějakou dobu v Unixu vůbec nebyl, takže je z těch dvou to bude ten méně významný, tedy ten co popisuje změnu metadat/inode (což je něco, co mě většinou nezajímá). </hint>

Kdy se poprvé objevila časová značka pro creation time, neboli birth time (btime), je těžké s jistotou říct, protože je možné, že to bylo v rámci nějakého proprietárního Unixového systému. A vzhledem k tomu, že takové systémy jsou v dnešní době většinou mrtvé bez dostupné dokumentace nebo zdrojového kódu pod rozumnou licencí, se mi ani nechce něco takového dohledávat. V rámci unixových systémů s otevřeným zdrojovým kódem je ale toto prvenství jasné: časová značka pro creation time se poprvé objevila až v roce 2003 ve FreeBSD 5.0 s příchodem souborového systému UFS2, a odtud se postupně rozšířila do ostatních BSD systémů, jako jsou NetBSD nebo OpenBSD.

Za povšimnutí stojí, jak podporu pro birth time ve FreeBSD přidali. Díky tomu, že FreeBSD mělo ve struktuře stat nevyužité místo, nebylo přidání další časové značky pojmenované st_birthtime do této struktury problém z hlediska zpětné kompatibility. Aktuálně se tato časová značka ale jmenuje st_birthtim, aby její pojmenování a význam odpovídalo konvenci z normy POSIX (viz tabulka výše).

OpenSolaris čas vzniku souboru sice také podporuje, ale strukturu stat ponechal beze změn. Pro získání hodnoty btime je tak třeba použít volání fgetattr(3C) a ze seznamu vrácených attributů přečíst A_CRTIME. Tato podpora je zdá se přítomna už v prvním commitu projektu OpenSolaris z roku 2005, takže pravděpodobně pochází ze Solarisu.

Jestli někdo uvažuje o přidání btime do POSIX standardu nevím, nepodařilo se mi o tom nic dohledat. Řekl bych, že to dnes asi už nikomu nestojí za námahu.

Podpora btime v Linuxových souborových systémech

Podobně jako jiná unixová jádra, Linux dlouhou dobu btime nepodporoval. Souborový systém ext3 nebo reiserfs btime neukládá a syscall stat(2) vrací strukturu stejného jména taktéž bez této časové značky. O podpoře btime v Linuxu se sice mluví už nějaký čas, ale na rozdíl od FreeBSD nešlo prostě přidat novou časovou značku někam do volného padding místa stávající struktury stat, protože Linux tam takové místo nemá. Místo definice nové verze struktury stat se tak ukázalo schůdnější navrhnout přidání btime do zcela nového volání xstat(), jehož začlenění do jádra se bohužel na nějakou dobu zadrhlo.

Linuxoví vývojáři nicméně začali přidávat podporu pro btime do nových souborových systémů dávno před tím, než bylo jasné, jak se to nakonec vyřeší. Např. ext4 dostal podporu pro btime již v roce 2007 v rámci patche přidávající podporu pro nanosekundové časové značky (diskový formát ext4 je stabilní od kernelu 2.6.28 z prosince 2008). Btrfs v roce 2012, přičemž jeho disk. formát je stabilní zhruba od listopadu 2013. Do XFS, které původně btime neimplementovalo, se tato podpora přidala v rámci změny přidávající kontrolní součty metadat v roce 2013 a je tak dostupná od jádra 3.10. To znamená, že i na relativně staré distribuci souborový systém dost možná ukládá pro každý soubor btime, i když tato informace není pro uživatele přímo přístupná. Bez podpory v kernelu se k ní lze většinou dostat přes debugging nástroje, které jsou ale pro každý souborový systém jiné, a které pochopitelně vyžadují root oprávnění pro přímý přístup k blokovému zařízení se souborovým systémem.

Jak na čtení btime za použití debug nástrojů

Nejdříve si (pro účely tohoto blogu) vytvoříme nové oddíly na hraní:

# mkfs.ext4 /dev/vdc
# mount /dev/vdc /mnt/test_ext4
# echo "ext4" > /mnt/test_ext4/testfile
# mkfs.xfs /dev/vdd
# mount /dev/vdd /mnt/test_xfs
# echo "xfs" > /mnt/test_xfs/testfile

Jen pro úplnost: použil systém s Debianem Stretch (aktuální stable), aby byla ukázka blíže realitě. Stretch totiž obsahuje kernel, který už má btime podporu pro ext4 i XFS, ale ještě neumí btime předat do userspace. Postup popsaný níže sice bude fungovat i na novějších distribucích, ale v momentě, kdy máme možnost použít syscall, nemá smysl se s tím takto párat. Jinak zahrnul bych sem i btrfs, ale nepodařilo se mi zjistit, jak z něj btime dostat.

V případě ext4 použijeme debugfs a jeho příkaz stat, v jehož výstupu najdeme čas vzniku souboru jako crtime:

# TZ=CET debugfs -R 'stat testfile' /dev/vdc
debugfs 1.43.4 (31-Jan-2017)
Inode: 12   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 1318526178    Version: 0x00000000:00000001
User:     0   Group:     0   Project:     0   Size: 5
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 8
Fragment:  Address: 0    Number: 0    Size: 0
 ctime: 0x5c66c5ee:2060896c -- Fri Feb 15 15:00:14 2019
 atime: 0x5c66c600:ee5ed49c -- Fri Feb 15 15:00:32 2019
 mtime: 0x5c66c5ee:2060896c -- Fri Feb 15 15:00:14 2019
crtime: 0x5c66c5ee:2060896c -- Fri Feb 15 15:00:14 2019
Size of extra inode fields: 32
Inode checksum: 0x0721e8ea
EXTENTS:
(0):32897

Pro soubor na XFS oddílu obdobně použijeme xfs_db. Nejdřív si však musíme zjistit inode souboru co nás zajímá a pak odpojit (nebo připojit read only) xfs filesystém. Čas vzniku souboru najdeme ve výpisu jako v3.crtime.sec a v3.crtime.nsec:

# ls -i /mnt/test_xfs/testfile
99 /mnt/test_xfs/testfile
# umount /mnt/test_xfs
# TZ=CET xfs_db /dev/vdd
xfs_db> inode 99
xfs_db> print
core.magic = 0x494e
core.mode = 0100644
core.version = 3
core.format = 2 (extents)
core.nlinkv2 = 1
core.onlink = 0
core.projid_lo = 0
core.projid_hi = 0
core.uid = 0
core.gid = 0
core.flushiter = 0
core.atime.sec = Fri Feb 15 16:11:36 2019
core.atime.nsec = 155502016
core.mtime.sec = Fri Feb 15 16:11:36 2019
core.mtime.nsec = 155502016
core.ctime.sec = Fri Feb 15 16:11:36 2019
core.ctime.nsec = 155502016
core.size = 0
core.nblocks = 0
core.extsize = 0
core.nextents = 0
core.naextents = 0
core.forkoff = 0
core.aformat = 2 (extents)
core.dmevmask = 0
core.dmstate = 0
core.newrtbm = 0
core.prealloc = 0
core.realtime = 0
core.immutable = 0
core.append = 0
core.sync = 0
core.noatime = 0
core.nodump = 0
core.rtinherit = 0
core.projinherit = 0
core.nosymlinks = 0
core.extsz = 0
core.extszinherit = 0
core.nodefrag = 0
core.filestream = 0
core.gen = 559694043
next_unlinked = null
v3.crc = 0x40d2f493 (correct)
v3.change_count = 3
v3.lsn = 0x100000002
v3.flags2 = 0
v3.cowextsize = 0
v3.crtime.sec = Fri Feb 15 16:11:36 2019
v3.crtime.nsec = 155502016
v3.inumber = 99
v3.uuid = 425730b5-1254-45db-8e31-87f25c75f6cd
v3.reflink = 0
v3.cowextsz = 0
u3 = (empty)

Pozor na to, že příkaz stat -v z xfs_io btime neukáže:

# mount /dev/vdd /mnt/test_xfs
# TZ=CET xfs_io -r /mnt/test_xfs/testfile -c 'stat -v'
fd.path = "/mnt/test_xfs/testfile"
fd.flags = non-sync,non-direct,read-only
stat.ino = 99
stat.type = regular file
stat.size = 0
stat.blocks = 0
stat.atime = Fri Feb 15 16:11:36 2019
stat.mtime = Fri Feb 15 16:11:36 2019
stat.ctime = Fri Feb 15 16:11:36 2019
fsxattr.xflags = 0x0 []
fsxattr.projid = 0
fsxattr.extsize = 0
fsxattr.cowextsize = 0
fsxattr.nextents = 0
fsxattr.naextents = 0
dioattr.mem = 0x200
dioattr.miniosz = 512
dioattr.maxiosz = 2147483136

Další potenciální zádrhel u XFS je, že podporu pro btime v XFS nenajdete na RHELu 7, protože jak jsme si řekli před chvílí, XFS umí ukládat btime až od jádra 3.10.

Čteme btime z Linuxového ext4 na FreeBSD

Vtipné je, že pokud připojíte Linuxem vytvořený ext4 filesystém na FreeBSD, tak pomocí nativního stat příkazu btime pro soubory uložené na tomto Linuxovém oddílu přečtete. A to navzdory tomu, že podpora Linuxových souborových systémů je na FreeBSD pochopitelně omezená, a např. to ext4 lze přes ext2fs připojit jen pro čtení (případně přes FUSE i pro zápis, ale to jsem nezkoušel).

Takto to dopadne, když se na FreeBSD 12 pokusíme přečíst btime na ext4 oddílu z předchozího pokusu. Pořadí časových značek ve výstupu je atime, mtime, ctime a btime:

# mount -t ext2fs -o ro /dev/vtbd1 /mnt/test_ext4
# cat /mnt/test_ext4/testfile
ext4
# env TZ=CET stat /mnt/test_ext4/testfile
92 12 -rw-r--r-- 1 root wheel 127754 5 "Feb 15 15:00:32 2019" "Feb 15 15:00:14 2019" "Feb 15 15:00:14 2019" "Feb 15 15:00:14 2019" 4096 8 0 /mnt/test_ext4/testfile

Podpora btime v GNU Linux distribucích

Takže podporu btime v Linuxových souborových systémech bychom měli. Ale aby nám to k něčemu bylo, je potřeba mít možnost předat tuto informaci z kernelu do userspace. Jak už jsem zmínil výše, btime mělo být možné získat pomocí volání xstat(), jehož začlenění se zadrhlo, aby se po několika letech vynořilo v nové podobě jako statx(), které se nakonec do jádra dostalo v Linuxu 4.11 z dubna 2017. Podpora v glibc existuje od glibc 2.28 ze srpna 2018. To znamená, že např. na Fedoře 29 se to dá už vyzkoušet.

Následující kód ukazuje, jak pomocí statx(2) přečíst pro daný soubor právě pouze btime. To, že je možné jádru říct o která metadata máme zájem, díky čemuž se jádro nemusí namáhat se zjišťováním hodnot, které stejně nepoužijeme, je mimochodem jedna z hlavních výhod volání statx(2) oproti stat(2).

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char**argv)
{
	struct statx stx = { 0, };
	if (argc != 2) {
		printf("Usage: %s FILE\n", argv[0]);
		printf("Display btime of a given file in UNIX time format.\n");
		return EXIT_SUCCESS;
	}
	int rc = statx(AT_FDCWD, argv[1], AT_SYMLINK_NOFOLLOW, STATX_BTIME, &stx);
	if (rc == 0) {
		if (stx.stx_btime.tv_sec != 0) {
			printf("@%u.%u\n", stx.stx_btime.tv_sec, stx.stx_btime.tv_nsec);
		} else {
			printf("-\n");
		}
	} else {
		perror("statx");
	}
	return rc;
}

Pokud máte na své distribuci glibc starší než 2.28 ale přitom jádro máte alespoň 4.11, musíte zavolat statx(2) s pomocí syscall(2).

Program vypisuje pouze samotnou časovou značku v unixovém formátu, zavináč na začátku je pro zjednodušení dekódování času pomocí nástroje date:

$ make btime
cc     btime.c   -o btime
$ ./btime btime
@1550254543.238843517
$ ./btime btime | date -f- --rfc-3339=ns
2019-02-15 19:15:43.238843517+01:00

Když si připojíme ext4 oddíl z předchozích pokusů, dostáváme očekávaný výsledek:

$ ./btime /mnt/test_ext4/testfile | date -f- --rfc-3339=ns
2019-02-15 15:00:14.135799387+01:00

Stat z GNU Coreutils

Jak jsem připomněl v úvodu, stat z GNU Coreutils stále vypisuje btime jako “-”. Nabízí se ale otázka, proč se s tím stat vůbec obtěžuje, když tu až do nedávné doby nebyla možnost, jak tuto informaci na Linuxu získat. Bližší pohled však ukáže, že v knihovně gnulib, kterou stat používá, byla podpora pro čtení btime ze struktury stat díky BSD* systémům implementována již v roce 2007. A samotný kód pro zobrazování btime se do stat(1) přidal už v roce 2010, hádám že v souvislosti s prvním návrhem systémového volání xstat(2), které se ale do jádra tehdy nakonec nedostalo. Každopádně díky tomu stat(1) od GNU Coreutils 8.6 z roku 2010 na Linuxu vypisuje btime s hodnotou “-” (a to bez ohledu na to, co je to za souborový systém), zatímco třeba na BSD systémech nebo Solarisu je schopný tyto hodnoty i zobrazovat, pokud je filesystém podporuje.

Další pohled na zdrojový kód odhalí, že díky hacku řešící podporu btime pro Solaris není až tak těžké tam btime s pomocí statx(2) volání dotat:

diff --git a/configure.ac b/configure.ac
index 669e9d1f2..081728c96 100644
--- a/configure.ac
+++ b/configure.ac
@@ -318,6 +318,8 @@ if test $ac_cv_func_getattrat = yes; then
   AC_SUBST([LIB_NVPAIR])
 fi
 
+AC_CHECK_FUNCS([statx])
+
 # SCO-ODT-3.0 is reported to need -los to link programs using initgroups
 AC_CHECK_FUNCS([initgroups])
 if test $ac_cv_func_initgroups = no; then
diff --git a/src/stat.c b/src/stat.c
index 0a5ef3cb4..189328cab 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -1007,6 +1007,24 @@ get_birthtime (int fd, char const *filename, struct stat const *st)
     }
 #endif
 
+#if HAVE_STATX
+  if (ts.tv_nsec < 0)
+    {
+      struct statx stx = { 0, };
+      if ((fd < 0
+           ? statx(AT_FDCWD, filename, AT_SYMLINK_NOFOLLOW, STATX_BTIME, &stx)
+           : statx(fd, "", AT_EMPTY_PATH, STATX_BTIME, &stx))
+          == 0)
+        {
+          if (stx.stx_btime.tv_sec != 0)
+            {
+              ts.tv_sec = stx.stx_btime.tv_sec;
+              ts.tv_nsec = stx.stx_btime.tv_nsec;
+            }
+        }
+    }
+#endif
+
   return ts;
 }
 

Podstata tohoto hacku je v tom, že se volá klasický stat(2) jako předtím a pak si navíc přes statx(2) ještě řekneme o btime. Na hraní to stačí:

$ touch ~/tmp/test
$ ./stat ~/tmp/test
  File: /home/martin/tmp/test
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: fd07h/64775d    Inode: 7377267     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  martin)   Gid: ( 1000/  martin)
Access: 2019-02-15 19:52:40.499658659 +0100
Modify: 2019-02-15 19:52:40.499658659 +0100
Change: 2019-02-15 19:52:40.499658659 +0100
 Birth: 2019-02-15 19:52:40.499658659 +0100
$ touch ~/tmp/test
$ ./stat ~/tmp/test
  File: /home/martin/tmp/test
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: fd07h/64775d    Inode: 7377267     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  martin)   Gid: ( 1000/  martin)
Access: 2019-02-15 19:52:46.598671520 +0100
Modify: 2019-02-15 19:52:46.598671520 +0100
Change: 2019-02-15 19:52:46.598671520 +0100
 Birth: 2019-02-15 19:52:40.499658659 +0100

Tohle “řešení” ale není zcela vhodné na začlenění do coreutils, protože používá zbytečně 2 volání jádra místo jednoho, a celé je to navíc postavená nad jiným hackem. K tomu abych stat upravil nějak rozumně jsem se ale zatím nedostal, a podle toho, že na coreutils listu mi nikdo neodpověděl, bych řekl, že na tom aktuálně nikdo nedělá.

Stat z GNU Bash

Trochu jsem se zhrozil, když jsem četl release notes pro Bash 5.0 z ledna 2019, kde mezi novinkami je:

  1. New loadable builtins: rm, stat, fdflags.

Na první pohled by to mohlo vypadat, že než se podaří do stat z coreutils přidat podporu pro btime, bude potřeba tuto práci udělat ještě jednou, protože s příchodem bashe 5 budou všichni používat stat implementovaný přímo v shellu, podobně jako např. v případě time:

$ type -a time
time is a shell keyword
time is /usr/bin/time
time is /bin/time

Ale ukázalo se, že to není tak horké, protože příslušný zdrojový kód stat.c se nachází v adresáři examples/loadables/, tj. jde o tzv. dynamic loadable buildin, a vnitřní funkce umístěné zde, např. cat.c nebo sleep.c, nejsou běžně v binárních balíčcích vůbec přítomné (jak si můžete ověřit pomocí výpisu enable -a). Idea za tímto je taková, že pokud potřebujete zoptimalizovat shell skript kde např. voláte ve smyčce sleep, můžete si zkompilovat příslušný buildin (případně si napsat vlastní) a pomocí enable -f ho do bashe načíst. Osobně mi sice přijde rozumnější psát takový script třeba v pythonu, ale pokud se není možné bashi vyhnout (např. protože jde o nějaký velký legacy skript), ta možnost tu je.

A jak už jsem naznačil, implementace loadable buildin funkce stat v bashi s btime pracovat neumí:

$ enable -f ~/projects/bash/examples/loadables/stat stat
$ help stat
stat: stat [-lL] [-A aname] file
    Load an associative array with file status information.

    Take a filename and load the status information returned by a
    stat(2) call on that file into the associative array specified
    by the -A option.  The default array name is STAT.  If the -L
    option is supplied, stat does not resolve symbolic links and
    reports information about the link itself.  The -l option results
    in longer-form listings for some of the fields. The exit status is 0
    unless the stat fails or assigning the array is unsuccessful.
$ stat ~/tmp/test
$ for i in "${!STAT[@]}"; do echo $i = ${STAT[$i]}; done
nlink = 1
link = /home/martin/tmp/test
perms = 0664
inode = 7377267
blksize = 4096
device = 64775
atime = 1550256766
type = -
blocks = 0
uid = 1000
size = 0
rdev = 0
name = /home/martin/tmp/test
mtime = 1550256766
ctime = 1550256766
gid = 1000

Ale v tomto případě mi přijde, že místo přidání podpory pro btime do této stat buildin funkce by bylo lepší napsat jinou, která by mohla lépe využívat možností jaderného volání statx(2).

Ostatní nástroje

Bohužel, podpora btime v základních komponentách GNU Linux distribucí zatím končí u statx(2) wrapperu v glibc. Stejně jako výše uvedené implementace nástroje stat, žádný základní nástroj jako např. ls nebo find s btime na Linuxu pracovat neumí. Přitom podobně jako v případě stat, např. find už základní podporu pro btime má, jen na Linuxu neumí jeho hodnotu zatím přečíst. Na druhou stranu, díky tomu že btime je možné číst pouze pomocí nového volání jádra statx(2), nebudou často změny v těchto nástrojích tak přímočaré, jak by se mohlo na první pohled zdát.

Dále také bude záležet na tom, zda se později neobjeví podpora pro změnu btime v jaderných voláních jako utimes(2) nebo utimensat(2). Aktuální stav, kdy není možné libovolně nastavit btime má svou logiku, čas vzniku souboru, pokud má opravdu dostát svému významu, by měl zůstat po zbytek života souboru stejný, ale na druhé straně to také znamená, že není možné např. archivovat soubor včetně btime pomocí cp -a nebo ho obnovit ze zálohy pomocí rsync. Z tohoto důvodu bude asi implementace podpory btime v GNU tar trvat trochu déle, protože není jasné, proč by tam někdo přidával podporu pro btime, když by pak tato informace nešla na Linuxu obnovit při rozbalování archivu.

Tady se hodí poznamenat, že FreeBSD možnost měnit btime pomocí utimes(2) nabízí od začátku, jak je popsané v článku o UFS2.

Co btime vlastně znamená a k čemu je to dobré?

Co vlastně znamená čas vzniku souboru? Jeden by řekl, že je to jasné, ale tak jednoduché to úplně není. Nejen vzhledem k výše zmíněné nemožnosti btime nastavit jde o low level informaci, o kterou např. při kopírování souboru přijdeme (z pohledu fs jde o nový soubor). Jiný častý případ kdy btime ztratíme je, když aplikace zapisuje do souboru atomicky s pomocí přejmenování dočasného souboru.

Btw nikdy předtím jsem si neuvědomil, že tohle atomické zapisování dělá např. i vim (všiměte si změny v inode a času vzniku souboru):

$ rm ~/tmp/test
$ touch ~/tmp/test
$ stat.hacked ~/tmp/test
  File: /home/martin/tmp/test
  Size: 0           Blocks: 0          IO Block: 4096   regular empty file
Device: fd07h/64775d    Inode: 7377286     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  martin)   Gid: ( 1000/  martin)
Access: 2019-02-17 09:51:45.483720811 +0100
Modify: 2019-02-17 09:51:45.483720811 +0100
Change: 2019-02-17 09:51:45.483720811 +0100
 Birth: 2019-02-17 09:51:45.483720811 +0100
$ vim ~/tmp/test
$ stat.hacked ~/tmp/test
  File: /home/martin/tmp/test
  Size: 5           Blocks: 8          IO Block: 4096   regular file
Device: fd07h/64775d    Inode: 7377267     Links: 1
Access: (0664/-rw-rw-r--)  Uid: ( 1000/  martin)   Gid: ( 1000/  martin)
Access: 2019-02-17 09:52:17.151767057 +0100
Modify: 2019-02-17 09:52:17.151767057 +0100
Change: 2019-02-17 09:52:17.156767065 +0100
 Birth: 2019-02-17 09:52:17.151767057 +0100

A tímto se konečně dostáváme k otázce k čemu je to btime vlastně dobré. Jak je vidět z doby, která byla potřeba aby se btime podpora dostala v použitelné podobě do jádra, nikdo tomu nepřipisuje velkou prioritu. To je vidět taky z toho, že změny implementující btime se často objevují v commitech, jejichž hlavní náplní je něco jiného. Ať už v případě ext4, kdy hlavní cíl byl implementovat nanosekundové časové značky. Podobně XFS přidává btime v rámci zavádění kontrolních součtů metadat a syscall statx(2) nebyl vytvořen jen kvůli čtení btime. Lecos naznačuje i to, za celou 50 letou historii Unixu to nikdo nenavrhl na přidání do POSIX standardu.

Když se podíváme na důvody implementace btime v Linuxu, kromě stručného “UFS2/ZFS to má taky” často vidíme zmínky o Sambě a kompatibilitě s Windows. Bohužel, Samba nemůže Linuxový btime v současné podobně přímo využít, protože Windows umožňuje čas vzniku souboru libovolně  měnit. Také NTFS-3G by mohl teoreticky čas vzniku souboru z Windows reportovat na Linuxu pomocí btime. Prakticky se tím ale nikdo nebude zabývat dokud se podpora pro statx(2) nepřidá do FUSE a alespoň nástroje z coreutils budou umět s btime pracovat. Navíc NTFS-3G už teď umí předat btime pomocí rozšířených atributů, i když možnost použít ls by byla rozhodně pohodlnější.

Nová časová značka se ale každopádně dá dobře využít při debugování nějakého podivného chování, kdy se každá stopa navíc hodí, ať už je za ním útočník, malware nebo ne zcela fungující software nebo hardware. Mimo těchto “detektivních” případů se btime dá využít i pro opačné účely. Např. by teoreticky šlo do souborových časových značek nepozorovaně ukládat malé množství dat. Paradoxně v obou případech je ale aktuální stav, kdy je btime podpora pouze v kernelu, vlastně výhodný. Pro forenzní analýzu je užitečné, že je vzhledem k menší povědomí o btime pravděpodobnost jeho falšování nižší. A pro opačné případy je zase pěkné, že “zneužívání” btime není tak na očích.

Reference

Články k tématu:

Historické zdroje:

       

Hodnocení: 100 %

        špatnédobré        

Anketa

Podpora času vzniku souboru (btime) v souborovém systému:
 (47 %)
 (47 %)
 (6 %)
Celkem 36 hlasů

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Nástroje: Začni sledovat (2) ?Zašle upozornění na váš email při vložení nového komentáře. , Tisk

Vložit další komentář

Bedňa avatar 17.2.2019 20:06 Bedňa | skóre: 34 | blog: Žumpa | Horňany
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Vieme o tom 1 - 2.

KERNEL ULTRAS video channel >>>
17.2.2019 21:25 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Ten článek čtenáře ze začátku napíná, jako kdyby se čas vzniku souboru dal z klasické trojice unixových časů přečíst :)
Toto správanie je však možné zmeniť, čím ale dôjde k porušeniu POSIX-u a niektoré aplikácie kvôli tomu nemusia pracovať správne.
Kromě věcí typu dump, co jiného nebude fungovat správně, když mám připojený souborový systém s volbou relatime? Vzhledem k tomu, že realtime je default snad všude a existují volby jako noatime, nevím co by se mělo s realtime rozbít.
Ak sa však pozrieme do histórie, hodnota ctime naozaj reprezentovala čas a dátum vytvorenia súboru (z angl. Creation Time). Postupne sa však z tejto hodnoty stala hodnoty času poslednej zmeny vlastností súboru tak, ako ho poznáme dnes.
Jinak jak píšu v blogu, tohle není pravda.
There is no point in being so cool in a cold world.
Bedňa avatar 17.2.2019 21:36 Bedňa | skóre: 34 | blog: Žumpa | Horňany
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Ja som myslel tie moje komentáre pod článkom, kde som sa to snažil osvetliť.
KERNEL ULTRAS video channel >>>
17.2.2019 22:54 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Ah, ok. Na jednu stranu je trochu škoda, že se to tenkrát zaseklo (to Linusovo "Let's wait five years and see" si z jaderných novinek taky pamatuju), ale na druhou stranu ho zcela chápu. Do Linux api nejde přidávat hned každou blbost :)
There is no point in being so cool in a cold world.
Gilhad avatar 17.2.2019 20:25 Gilhad | skóre: 20 | blog: gilhadoviny
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Ono je to hlavně filosofický problém - pokud mám řekněme delší text, co jsem začal psát předloni a letos ho rozdělím do deseti kapitol, tak se ty kapitoly zrodily převážně loni, ctime bude teď a co jako má ten birthtime vlastně vůbec znamenat?

- čas, kdy jsem začal kapitolu psát? tedy nějaké loňské datum?

- čas, kdy jsem začal psát ten traktát? tedy předloni?

- čas, kdy jsem ten soubor uložil pod novým jménem? tedy teď? A co když ho zítra přejmenuju z c7.txt na popisnější ch_07_co_je_čas.txt?

- čas, kdy se vlastně ta myšlenka popsaná v té kapitole zrodila? U mě před třemi lety, ale o podobné věci už debatovali staří řekové a římané, tedy spíš někde kolem začátku letopočtu?

Imho jediný rozumný čas je to, co uvedu přímo v textu toho souboru, ostatní možnosti většinou nedávají dobrý konzistentní smysl - kdy to bylo naposled modifikované a kdy ten konkrétní soubor na tom filesystému vzniknul už stejně máme...
17.2.2019 21:41 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Ono ta btime značka mi vzhledem k její nízkoúrovňové povaze přijde pro běžného uživatele na pokraji použitelnosti.

Ale ten tvůj příklad je něco, co lze pěkně řešit pomocí gitu. Začnu psát a postupně dělám commity když dokončím nějaký dílčí celek textu. Ten může růst a přesovat se mezi soubory, ale všechny informace, na které se ptáš, jdou přes git získat zpětně. A až na případ s rozdělením jednoho souboru do 10 menších a ten filosofický případ s Řeky a Římany dokáže git dát odpověď dohromady zcela automaticky :)

Viz. příklad z toho Unix history repa, kde je výstup z git blame:
3cc1108b usr/sys/ken/pipe.c     (Ken Thompson 1974-11-26 18:13:21 -0500  53) 	rf->f_flag = FREAD|FPIPE;
3cc1108b usr/sys/ken/pipe.c     (Ken Thompson 1974-11-26 18:13:21 -0500  54) 	rf->f_inode = ip;
3cc1108b usr/sys/ken/pipe.c     (Ken Thompson 1974-11-26 18:13:21 -0500  55) 	ip->i_count = 2;
[...]
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 122) 	register struct inode *ip;
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 123) 
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 124) 	ip = fp->f_inode;
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 125) 	c = u.u_count;
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 126) 
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 127) loop:
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 128) 
1f183be2 usr/sys/sys/pipe.c     (Ken Thompson 1979-01-10 15:19:35 -0500 129) 	/*
9a9f6b22 usr/src/sys/sys/pipe.c (Bill Joy     1980-01-05 05:51:18 -0800 130) 	 * If error or all done, return.
9a9f6b22 usr/src/sys/sys/pipe.c (Bill Joy     1980-01-05 05:51:18 -0800 131) 	 */
9a9f6b22 usr/src/sys/sys/pipe.c (Bill Joy     1980-01-05 05:51:18 -0800 132) 
9a9f6b22 usr/src/sys/sys/pipe.c (Bill Joy     1980-01-05 05:51:18 -0800 133) 	if (u.u_error)
9a9f6b22 usr/src/sys/sys/pipe.c (Bill Joy     1980-01-05 05:51:18 -0800 134) 		return;
6d632e85 usr/sys/ken/pipe.c     (Ken Thompson 1975-07-17 10:33:37 -0500 135) 	plock(ip);
6d632e85 usr/sys/ken/pipe.c     (Ken Thompson 1975-07-17 10:33:37 -0500 136) 	if(c == 0) {
6d632e85 usr/sys/ken/pipe.c     (Ken Thompson 1975-07-17 10:33:37 -0500 137) 		prele(ip);
6d632e85 usr/sys/ken/pipe.c     (Ken Thompson 1975-07-17 10:33:37 -0500 138) 		u.u_count = 0;
6d632e85 usr/sys/ken/pipe.c     (Ken Thompson 1975-07-17 10:33:37 -0500 139) 		return;
6d632e85 usr/sys/ken/pipe.c     (Ken Thompson 1975-07-17 10:33:37 -0500 140) 	}
Imho jediný rozumný čas je to, co uvedu přímo v textu toho souboru, ostatní možnosti většinou nedávají dobrý konzistentní smysl
Souhlasím, pro uživatele jsou často zajímavější metadata datového formátu (ať už je to ten výše zmíněný git, nebo např. exif data ve fotce) než to, co ukládá souborový systém. To ale neznamená, že by to šlo z něj vyhodit.
kdy ten konkrétní soubor na tom filesystému vzniknul už stejně máme...

Moment, to je ten btime, o kterém jsem psal. Nebo jsem nepochopil, jak to myslíš.
There is no point in being so cool in a cold world.
18.2.2019 10:03 Xerces
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Nejprve musím pochválit autora za perfektní přehled. Moc dobře se to četlo i když člověk tušil jak to dopadne :-) Jinak souhlasím s uživatelem Gilhad, že je to spíše filosofický problém. Stejně jako čas zrušení souboru se jedná o extrém, který podle mě nemá význam evidovat. Ostatně i závěr autora včetně uvedených důvodů v poslední kapitole to zmiňuje. Proč se tedy snažit implementovat něco takového, když by ten přínos nebyl jednoznačný?
xkucf03 avatar 18.2.2019 10:23 xkucf03 | skóre: 49 | blog: xkucf03
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích

Když už FS tu informaci ukládají, tak by to chtělo ji dotáhnout i do uživatelského rozhraní. (případně odmazat z implementací těch FS, třeba tam všude dávat nulu)

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
xkucf03 avatar 18.2.2019 00:01 xkucf03 | skóre: 49 | blog: xkucf03
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin

Díky za článek.

V anketě jsem dal „naprosto zásadní“ – ono to tedy většinou zásadní není, ale občas by to mohla být pěkná zrada a mohla by tímto kanálem prosáknout informace, která by prosáknout neměla. Z tohoto důvodu doufám, že budou brzo dostupné nástroje pro přepis této informace, aby to člověk nemusel hackovat přímým přepisováním příslušných bajtů na blokovém zařízení.

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
18.2.2019 07:20 Filip Jirsák | skóre: 68 | blog: Fa & Bi
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Třeba cp?
18.2.2019 09:34 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Ano, ale není to vždy bez komplikací. Třeba pokud není dost volného místa na disku nebo u neprázdného adresáře, který není možné jednoduše přesunout (např. kdybych chtěl změnit btime u svého domovského adresáře).
There is no point in being so cool in a cold world.
18.2.2019 09:44 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Na druhou stranu prosáknutí hrozí jen pokud si někdo zajistí přístup k tvému souborovému systému, což se dá řešit např. šifrováním celého disku, protože na něm budou pravděpodobně i jiné zajímavé věci, než jen btime značky na souborech.

Btw z forenzního hlediska jsou imho nejzajímavější btime značky na adresářích.

Ale jinak souhlas, přístup co zvolilo FreeBSD mi přijde osobně rozumnější.
There is no point in being so cool in a cold world.
18.2.2019 08:14 danc
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Diky za skvele ctivy clanek! Jestli to tu jeste aspon trochu zije, bylo by hezke, kdyby tento text vysel na hlavni strance jako clanek a reakce poslala autorovi nejakou korunu ;-)
18.2.2019 22:35 Bherzet | skóre: 19 | blog: Bherzetův blog
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Nenapadlo by mě, že historie jednoho souborového atributu může být tak zajímavá. Díky za fakt pěkně zpracovaný článek.

Trochu OT, ale vzpomněl jsem si na otázku, kterou jsme kdysi řešili s kolegou: Co se stane při přenesení souborů (vč. atributů) na systém, kde je pod stejným UID jiný uživatel? Chtěl jsem to vyzkoušet, ale nějak to zapadlo a nedostal jsem se k tomu. Předpokládám, že se stane přesně to, co by se dalo čekat, tj. majitelem souboru bude uživatel s daným UID (bez ohledu na to, že třeba username se liší). Nedokážu si představit, proč by to tak být nemělo, takže druhá otázka pak je, jak tomu předejít. Umím si představit, jak to řešit technicky, ale přijde mi, že tohle je přesně věc, kterou lze velmi snadno přehlédnout a pak se chvíli divit, co se děje. Možná zálohovat i /etc/passwd a při obnovování ověřit, že na cílovém systému danému UID odpovídá stejný uživatel (resp. username)? Umí to nějaký standardní nástroj?
xkucf03 avatar 18.2.2019 23:07 xkucf03 | skóre: 49 | blog: xkucf03
Rozbalit Rozbalit vše Shoda UID na externím disku

V rámci jedné organizace bývá obvykle snaha, aby jeden uživatel měl všude stejné UID (je na to např. atribut v LDAPu).

Připojovat někam cizí disk není úplně typický scénář a na výměnných médiích (diskety, USB flash…) býval většinou FAT, u kterého si vlastníka/práva zadáš při připojování. Ale když někam připojíš třeba záložní HDD s Ext4, tak se může stát, že než se rozkoukáš, už jiný uživatel z toho disku čte, protože má náhodou stejné UID jako třeba ty na jiném počítači… to už problém je. Tam musíš dát adresář, kam připojuješ, do adresáře, kam ostatní nevidí, a pak zkontrolovat práva a případně změnit vlastníky.

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
18.2.2019 23:57 Bherzet | skóre: 19 | blog: Bherzetův blog
Rozbalit Rozbalit vše Re: Shoda UID na externím disku
V organizacích asi jo, ale že mám na svých systémech všude stejný UID je v podstatě náhoda. Vím, že bych na to měl myslet, ale prostě mám vždycky nepříjemný pocit, když narazím na něco podobného (kolik času už jsem strávil debugováním i daleko zjevnějších omylů…). Stejně teď budu muset nějak „zrefactorovat“ a dořešit zálohování, tak si říkám, že bych fakt mohl přidat ten /etc/passwd (i k nesystémovým zálohám) a skript na obnovení, který to rovnou diffne proti aktuálnímu a upozorní na nesrovnalosti… To není tolik práce navíc a obnovovací skript (nebo nějaké README) chci mít na záloze asi stejně.
19.2.2019 00:00 Bherzet | skóre: 19 | blog: Bherzetův blog
Rozbalit Rozbalit vše Re: Shoda UID na externím disku
(Protože jakmile bych překopíroval hromadu souborů do nějaké existující adresářové struktury, tak opravovat potom ty práva všude by byl fakt opruz. U jednoho souboru/adresáře by to ani nestálo za řeč.)
Gilhad avatar 19.2.2019 02:54 Gilhad | skóre: 20 | blog: gilhadoviny
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
závisí na způsobu přenosu - vyhledej si u rsync parametr --numeric-ids ten se právě tímnto zabývá (defaultně se kopíruje tak, aby zůstalo zachováno jméno (nikoli id) uživatele a skupiny, ale jsou různé problémy okolo toho)
19.2.2019 09:50 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Tohle je vlastně speciální případ. Při kopírování souboru se UID zachová pouze pokud běží pod rootem a řekneš si o to (např. přes cp -a, rsync -a nebo při rozbalování tarballu). Což se běžně děje např. při obnovoání záloh. A ano, majitelem souboru bude uživatel s daným UID bez ohledu na to, že třeba username se liší.

Btw gnu tar tohle nějak řeší, protože ukládá jak UID tak jméno (viz volby --no-same-owner, --numeric-owner, --owner=NAME[:UID], --owner-map=FILE).

Já svých strojích vytvářím uživatele ansible playbookem a zálohuju jen celý /home. Takže postup obnovení je spustit playbook a pak přes rsync zkopírovat celý /home.
There is no point in being so cool in a cold world.
19.2.2019 16:53 Václav HFechs Švirga | skóre: 26 | blog: HF | Kopřivnice
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Hlasoval jsem špatně (druhá volba, spíš jsem měl hlasovat pro třetí).

Využil jsem birth date pro jeden ošklivý workaround na jednom starším serveru. Běží na něm aplikace, kde jde přes apache+php uploadovat nějaké soubory a frontend přes sessions zobrazuje progres uploadu. Verze apache co tam běží (či PHPka) měla nějaký bug, že když byl soubor větší tuším více než 2 GB, session od té velikosti začala vracet nesmysly o velikosti uploadovaného souboru (přetekl nějaký int), upload ale po čase správně doběhl.

Provizorně se to zalepilo hackem (časem to nejspíš vyřeší aktualizace serveru), že pokud byl soubor větší než 2 GB, session se ignorovala a přímo se zjišťuje velikost souboru v /tmp. Problém byl najít správný soubor (název se dá zjistit až po doběhnutí uploadu). Ne úplně spolehlivá detekce (kdyby bylo více uploadů v jeden čas, nebude to fungovat, ale to se příliš neděje + upload tak velkých souborů není častý + způsobí to jen nefunkčnost progresu) funguje tak, že se projedou všechny tmp soubory odpovídající masce a najde se ten, který má nejbližší čas vytvoření od začátku uploadu.

Filesystém byl naštěstí ext4, tak se to naprasilo přes debugfs (skript, který user s aplikací schopný spustit přes sudo).
Baník pyčo!
19.2.2019 22:48 debian+
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Autorovy a vsetkym: https://lwn.net/Articles/397442/
19.2.2019 22:54 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Však ano, tento článek z roku 2010 je nejlepší popis btime, co na lwn.net vyšel. Linkuju ho v blogu hned třikrát, z toho poslední link je v závěrečném přehledu, včetně českého překladu, co vyšel tady na abclinuxu v rámci jaderných novinek.
There is no point in being so cool in a cold world.
22.2.2019 22:24 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Btw časovou značku pojmenovanou btime v Linuxu najdeme ještě v /proc/stat, kde ale znamená boot time, tj. čas kdy systém nabootoval, v unixovém formátu se sekundovou přesností:
$ grep btime /proc/stat
btime 1550868084
$ grep btime /proc/stat | awk '{ print "@"$2 }' | date -f- 
Fri Feb 22 21:51:24 CET 2019
There is no point in being so cool in a cold world.
6.3.2019 14:06 uruk
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Po začištění hran:
$ awk '$1 == "btime" {print strftime("%FT%T",$2)}' /proc/stat
2019-02-21T14:02:24
15.3.2019 23:17 marbu | skóre: 31 | blog: hromada | Brno
Rozbalit Rozbalit vše Re: Jak je to s časem vzniku souboru na GNU Linux distribucích
Odpovědět | Sbalit | Link | Blokovat | Admin
Malý update: ten patch pro stat se po několika malých úpravách nakonec dostal do upstreamu. Viz. sekce Improvements v oznámení o vydání GNU coreutils verze 8.31.
There is no point in being so cool in a cold world.

Založit nové vláknoNahoru

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.