From owner-freebsd-questions@freebsd.org Thu Oct 1 21:46:33 2020 Return-Path: Delivered-To: freebsd-questions@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 9D125434FE7 for ; Thu, 1 Oct 2020 21:46:33 +0000 (UTC) (envelope-from kh@panix.com) Received: from mailbackend.panix.com (mailbackend.panix.com [166.84.1.89]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 4C2RXS660sz3Vfl for ; Thu, 1 Oct 2020 21:46:32 +0000 (UTC) (envelope-from kh@panix.com) Received: from rain.home (pool-173-48-64-3.bstnma.fios.verizon.net [173.48.64.3]) by mailbackend.panix.com (Postfix) with ESMTPSA id 4C2RXS02sMz1nyy for ; Thu, 1 Oct 2020 17:46:31 -0400 (EDT) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="6IfbR40u5C" Content-Transfer-Encoding: 7bit Message-ID: <24438.20016.682769.47891@rain.home> Date: Thu, 1 Oct 2020 17:46:24 -0400 From: Kurt Hackenberg To: freebsd-questions@freebsd.org Subject: Re: Preserving target file's creation date In-Reply-To: <20201001141721.5be6318e@gumby.homeunix.com> References: <202010010424.0914OZ9Y029194@sdf.org> <20201001072728.000004b6@seibercom.net> <20201001134113.13ff6d86.freebsd@edvax.de> <20201001141721.5be6318e@gumby.homeunix.com> X-Mailer: VM 8.2.0b under 26.3 (amd64-portbld-freebsd13.0) X-Rspamd-Queue-Id: 4C2RXS660sz3Vfl X-Spamd-Bar: - Authentication-Results: mx1.freebsd.org; dkim=none; dmarc=none; spf=pass (mx1.freebsd.org: domain of kh@panix.com designates 166.84.1.89 as permitted sender) smtp.mailfrom=kh@panix.com X-Spamd-Result: default: False [-1.64 / 15.00]; RCVD_TLS_ALL(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; ARC_NA(0.00)[]; FROM_HAS_DN(0.00)[]; RWL_MAILSPIKE_GOOD(0.00)[166.84.1.89:from]; TO_MATCH_ENVRCPT_ALL(0.00)[]; R_SPF_ALLOW(-0.20)[+ip4:166.84.0.0/16]; MIME_GOOD(-0.10)[multipart/mixed,text/plain]; TO_DN_NONE(0.00)[]; PREVIOUSLY_DELIVERED(0.00)[freebsd-questions@freebsd.org]; RCPT_COUNT_ONE(0.00)[1]; NEURAL_HAM_LONG(-0.74)[-0.744]; DMARC_NA(0.00)[panix.com]; RCVD_IN_DNSWL_MED(-0.20)[166.84.1.89:from]; CTYPE_MIXED_BOGUS(1.00)[]; NEURAL_HAM_SHORT(-0.46)[-0.457]; NEURAL_HAM_MEDIUM(-0.94)[-0.940]; FROM_EQ_ENVFROM(0.00)[]; R_DKIM_NA(0.00)[]; MIME_TRACE(0.00)[0:+,1:+,2:+]; ASN(0.00)[asn:2033, ipnet:166.84.0.0/16, country:US]; RCVD_COUNT_TWO(0.00)[2]; MAILMAN_DEST(0.00)[freebsd-questions]; RECEIVED_SPAMHAUS_PBL(0.00)[173.48.64.3:received] X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 01 Oct 2020 21:46:33 -0000 --6IfbR40u5C Content-Type: text/plain; charset=us-ascii Content-Description: message body text Content-Transfer-Encoding: 7bit RW via freebsd-questions writes: >There are four timestamps: atime, mtime, ctime and btime. > >The first two are data access and modification. ctime is when the >metadata in the inode was last modified, the 'c' is for changed, not >created. > >btime is time the file/inode was created (b for birth), but it's not >portable. Yes. Historically, there were three file times: atime, mtime, ctime (historically called creation time, though it's actually been inode modification time for as long as I know of). The fourth, birth time, was added much later, and I think only in FreeBSD. To maximize confusion, people sometimes call this creation time, too. Don't do that. Somebody who has Linux handy could check what file times it has. You might look at what comes back from the system call stat(). >I just had a look at some files I recently copied with dump|restore and >it had preserved all 4 times. I also found: > >cp -p preserved atime, mtime and btime. > >rsync -a preserved mtime and btime > >I find the last two results strange as cp(1) and rsync(1) don't claim >to preserve btime. I'd be surprised if rsync even knows about it. I just found that cp without -p preserves birth time, as you would hope, though ctime changes. Perhaps some of these old utilities that run on many Unixes don't know about the FreeBSD birth time. I'll attach to this message a C program I wrote that displays all four file times. We'll see whether the mailing list allows the attachment. (In the past this list has removed attachments of type text/x-csrc; I'll make this one text/plain). --6IfbR40u5C Content-Type: text/plain; name="ftime4.c" Content-Description: ftime4.c Content-Disposition: inline; filename="ftime4.c" Content-Transfer-Encoding: 7bit /* FreeBSD program: for each file named on command line, display all four times. The Unix file time traditionally called creation time has been, for as long as I remember, updated whenever the inode contents are modified. FreeBSD adds a fourth time, "birth time" (aka creation time), which is when the file (inode) was created. This program can display the times as local time or UTC, with or without nanoseconds. The two output formats (with or without nanoseconds) are substantially different. */ #include #include #include #include #include #include #include typedef int BOOL; #define TRUE 1 #define FALSE 0 static void qerror(const char *me, const char *thing) { fprintf(stderr, "%s: %s: %s\n", me, thing, strerror(errno)); } static void stringify(const struct timespec ts, const BOOL worldtime, const BOOL nanoseconds, char *str) { struct tm tm; (void)(worldtime ? gmtime_r : localtime_r)(&ts.tv_sec, &tm); if (nanoseconds) (void)sprintf(str, "%04d/%02d/%02d %02d:%02d:%02d.%09ld", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec); else { (void)asctime_r(&tm, str); str[strlen(str) - 1] = '\0'; } sprintf(&str[strlen(str)], " %s (%c%02ld:%02ld:%02ld)", tm.tm_zone, (tm.tm_gmtoff >= 0L) ? '+' : '-', labs(tm.tm_gmtoff) / 3600L, labs(tm.tm_gmtoff) / 60L % 60L, labs(tm.tm_gmtoff) % 60L); } int main(int argc, const char *argv[], const char *envp[]) { const char *me; BOOL worldtime = FALSE; /* display times as UTC */ BOOL nanoseconds = FALSE; /* display times with nanoseconds */ struct stat stuff; char bstr[100]; char cstr[100]; char mstr[100]; char astr[100]; int ai; /* argv index */ int aj; /* argv[ai] (string) index */ int err; if ((me = strrchr(argv[0], '/')) != NULL) me++; else me = argv[0]; err = 0; for (ai = 1; ai < argc && (argv[ai])[0] == '-'; ai++) for (aj = 1; (argv[ai])[aj] != '\0'; aj++) switch ((argv[ai])[aj]) { case 'u': /* UTC */ worldtime = TRUE; break; case 'l': /* local time */ worldtime = FALSE; break; case 'n': /* nanoseconds */ nanoseconds = TRUE; break; case 's': /* seconds */ nanoseconds = FALSE; break; default: fprintf(stderr, "%s: unknown option '%c'\n", me, (argv[ai])[aj]); err = -1; break; } if (ai < argc) do if (stat(argv[ai], &stuff) == 0) { stringify(stuff.st_birthtim, worldtime, nanoseconds, bstr); stringify(stuff.st_ctim, worldtime, nanoseconds, cstr); stringify(stuff.st_mtim, worldtime, nanoseconds, mstr); stringify(stuff.st_atim, worldtime, nanoseconds, astr); printf("%s %s %s %s %s\n", bstr, cstr, mstr, astr, argv[ai]); } else { qerror(me, argv[ai]); err = errno; } while (++ai < argc); else { fprintf(stderr, "%s usage: %s [-ulns] file ...\n", me, me); err = -1; } return err; } --6IfbR40u5C--