Apparently there is something wrong with the debian stretch utimensat
system call, or with its interaction with cifs. It works as expected
when the destination file is on a ext4 file system, but it does not work
when the destination file is on a SMB file system.
I wrote a simple C program, which I compiled with <gcc -g -o x2 x2.c>.
On my debian buster workstation, I run the program using a script, which is:
#!/bin/bash
NAME='/mnt/u1/rw/receipt/test2.txt'
rm -f "${NAME}"
ls -ls "${NAME}"
/mnt/1g/home/u1/data/cp-pi/x2 "${NAME}"
ls -ls "${NAME}"
sleep 1
ls -ls "${NAME}"
Note that the /mnt/u1/rw/receipt is a SMB folder. I got this result:
$ ./do2.sh
ls: cannot access '/mnt/u1/rw/receipt/test2.txt': No such file or directory
0 -rwxr-xr-x 1 u1 u1 10 Feb 5 2017 /mnt/u1/rw/receipt/test2.txt
1024 -rwxr-xr-x 1 u1 u1 10 Apr 30 12:20 /mnt/u1/rw/receipt/test2.txt
As you can see, the time stamp changes after one second.
This is the C code for x2.
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
static char *data = "test data\n";
static struct timespec timestamps [2] = {
{ 1588174263, 908624390 },
{ 1486350336, 481422339 }
};
int main (int argc, char **argv)
{
int fd;
if (argc > 1) {
fd = openat (AT_FDCWD, argv [1], O_WRONLY|O_CREAT, 0666);
if (fd >= 0) {
write (fd, data, strlen (data));
/* do not use glibc utimensat directly, it does not allow
NULL as a second argument */
syscall (SYS_utimensat, fd, NULL, timestamps, 0);
close (fd);
return 0;
}
}
printf ("something went wrong\n");
return 0;
}
About my buster workstation:
# cat /proc/version;dpkg -l |grep cifs
Linux version 4.19.0-8-amd64 (debian-ker...@lists.debian.org) (gcc
version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.98-1+deb10u1 (2020-04-27)
ii cifs-utils 2:6.8-2 amd64 Common Internet File System utilities
I run the same binary and script on my debian stretch workstation, and
got this:
$ ./do2.sh
ls: cannot access '/mnt/u1/rw/receipt/test2.txt': No such file or directory
0 -rwxr-xr-x 1 u1 u1 10 Feb 5 2017 /mnt/u1/rw/receipt/test2.txt
4 -rwxr-xr-x 1 u1 u1 10 Feb 5 2017 /mnt/u1/rw/receipt/test2.txt
$ cat /proc/version
Linux version 4.9.0-12-amd64 (debian-ker...@lists.debian.org) (gcc
version 6.3.0 20170516 (Debian 6.3.0-18+deb9u1) ) #1 SMP Debian
4.9.210-1 (2020-01-20)
# dpkg -l |grep cifs
ii cifs-utils 2:6.7-1 amd64 Common Internet File System utilities
I run the C program above, using the same binary, and got two different
behaviors.
Can anyone help me with this?
On 4/29/20 5:31 PM, Thomas Schmitt wrote:
Hi,
assumed that the success of "touch" indicates that utimensat(2) works
fine, i would pick the failed fsetxattr(2) as next suspect.
Does this set the timestamps despite failing ?
setfattr -n user.test_name -v test_value /mnt/u1/rw/receipt/u1.crontab
(I expect an "Operation not supported" error as in strace.
If it succeeds against our will, try -n "test_name", without prefix
"user.".)
Alberto Sentieri wrote:
So, the cp behavior on debian stretch and buster seems to be the same.
But the implementation of the system calls is not.
touch does the trick of dup2 and close, before calling utimensat.
Hm. To verify suchtheories you will have to create a C program which
uses the traced system calls and by which you can test variations.
Quite interesting would be to inquire the file timestamps immediately
after utimensat() in order to learn whether it gets into effect at
least for a short time.
Have a nice day :)
Thomas