Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File::Copy::move does not move when destination is hardlink to source #10009

Open
p5pRT opened this issue Dec 7, 2009 · 4 comments
Open

File::Copy::move does not move when destination is hardlink to source #10009

p5pRT opened this issue Dec 7, 2009 · 4 comments

Comments

@p5pRT
Copy link

p5pRT commented Dec 7, 2009

Migrated from rt.perl.org#71082 (status was 'open')

Searchable as RT71082$

@p5pRT
Copy link
Author

p5pRT commented Dec 7, 2009

From perlbug@plan9.de

Created by perlbug@plan9.de

File​::Copy​::move silently fails to move a file if the destination path
happens to be a hardlink to the same file as the source path. The effetc
is that it returns success, but both source and destination paths still
exist.

The problem is likely that it uses rename but doesn't check whether rename
actually does something (rename simply returns sucecss if source and
destination refer to the same file).

Perl Info

Flags:
    category=library
    severity=low

Site configuration information for perl 5.10.0:

Configured by Marc Lehmann at Sat Feb 21 02:30:27 CET 2009.

Summary of my perl5 (revision 5 version 10 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.6.24-etchnhalf.1-amd64, archname=amd64-linux
    uname='linux cerebro 2.6.24-etchnhalf.1-amd64 #1 smp mon jul 21 10:36:02 utc 2008 x86_64 gnulinux '
    config_args='-Duselargefiles -Dxxxxuse64bitint -Uuse64bitall -Dusemymalloc=n -Dcc=gcc -Dccflags=-ggdb -gdwarf-2 -g3 -Dcppflags=-DPERL_ARENA_SIZE=16368 -D_GNU_SOURCE -I/opt/include -Doptimize=-O6 -msse2 -funroll-loops -fno-strict-aliasing -Dcccdlflags=-fPIC -Dldflags=-L/opt/perl/lib -L/opt/lib -Dlibs=-ldl -lm -lcrypt -Darchname=amd64-linux -Dprefix=/opt/perl -Dprivlib=/opt/perl/lib/perl5 -Darchlib=/opt/perl/lib/perl5 -Dvendorprefix=/opt/perl -Dvendorlib=/opt/perl/lib/perl5 -Dvendorarch=/opt/perl/lib/perl5 -Dsiteprefix=/opt/perl -Dsitelib=/opt/perl/lib/perl5 -Dsitearch=/opt/perl/lib/perl5 -Dsitebin=/opt/perl/bin -Dman1dir=/opt/perl/man/man1 -Dman3dir=/opt/perl/man/man3 -Dsiteman1dir=/opt/perl/man/man1 -Dsiteman3dir=/opt/perl/man/man3 -Dman1ext=1 -Dman3ext=3 -Dpager=/usr/bin/less -Uafs -Uusesfio -Uusenm -Uuseshrplib -Dd_dosuid -Dusethreads=undef -Duse5005threads=undef -Duseithreads=undef -Dusemultiplicity=undef -Demail=perl-binary@plan9.de -Dcf_email=perl-binary@plan9.de -Dcf_by=Marc Lehmann -Dlocincpth=/opt/perl/include /opt/include -Dmyhostname=localhost -Dmultiarch=undef -Dbin=/opt/perl/bin -Dxxxusedevel -DxxxDEBUGGING -Dxxxuse_debugging_perl -Dxxxuse_debugmalloc -des'
    hint=recommended, useposix=true, d_sigaction=define
    useithreads=undef, usemultiplicity=undef
    useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
    use64bitint=define, use64bitall=undef, uselongdouble=undef
    usemymalloc=n, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-ggdb -gdwarf-2 -g3 -fno-strict-aliasing -pipe -I/opt/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
    optimize='-O6 -msse2 -funroll-loops -fno-strict-aliasing',
    cppflags='-DPERL_ARENA_SIZE=16368 -D_GNU_SOURCE -I/opt/include -ggdb -gdwarf-2 -g3 -fno-strict-aliasing -pipe -I/opt/include'
    ccversion='', gccversion='4.3.2', gccosandvers=''
    intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
    ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
    alignbytes=8, prototype=define
  Linker and Libraries:
    ld='gcc', ldflags ='-L/opt/perl/lib -L/opt/lib -L/usr/local/lib'
    libpth=/usr/local/lib /lib /usr/lib /lib64 /usr/lib64
    libs=-ldl -lm -lcrypt
    perllibs=-ldl -lm -lcrypt
    libc=/lib/libc-2.7.so, so=so, useshrplib=false, libperl=libperl.a
    gnulibc_version='2.7'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
    cccdlflags='-fPIC', lddlflags='-shared -O6 -msse2 -funroll-loops -fno-strict-aliasing -L/opt/perl/lib -L/opt/lib -L/usr/local/lib'

Locally applied patches:
    http://public.activestate.com/cgi-bin/perlbrowse/p/34209
    http://public.activestate.com/cgi-bin/perlbrowse/p/34507
    http://www.gossamer-threads.com/lists/perl/porters/232549
    embed.fnc:Perl_vcroak NULLOK


@INC for perl 5.10.0:
    /root/src/sex
    /opt/perl/lib/perl5
    /opt/perl/lib/perl5
    /opt/perl/lib/perl5
    /opt/perl/lib/perl5
    /opt/perl/lib/perl5
    .


Environment for perl 5.10.0:
    HOME=/root
    LANG (unset)
    LANGUAGE (unset)
    LC_CTYPE=en_US.UTF-8
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/root/s2:/root/s:/opt/bin:/opt/sbin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11/bin:/usr/games:/usr/local/bin:/usr/local/sbin:/root/pserv:.
    PERL5LIB=/root/src/sex
    PERL5_CPANPLUS_CONFIG=/root/.cpanplus/config
    PERLDB_OPTS=ornaments=0
    PERL_ANYEVENT_DBI_TESTS=1
    PERL_ANYEVENT_EDNS0=1
    PERL_ANYEVENT_NET_TESTS=1
    PERL_ANYEVENT_PROTOCOLS=ipv4,ipv6
    PERL_ANYEVENT_STRICT=1
    PERL_BADLANG (unset)
    PERL_UNICODE=E
    SHELL=/bin/bash

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2011

From @jkeenan

On Sun Dec 06 16​:58​:15 2009, perlbug@​plan9.de wrote​:

File​::Copy​::move silently fails to move a file if the destination path
happens to be a hardlink to the same file as the source path. The
effetc
is that it returns success, but both source and destination paths
still
exist.

The problem is likely that it uses rename but doesn't check whether
rename
actually does something (rename simply returns sucecss if source and
destination refer to the same file).

To my surprise, I get different results on different OSes when I try to
reproduce this phenomenon. In my case, the two OSes are Linux and Darwin.

On both OSes​:
###
$ cat alpha.txt
$class = {
  alpha => 'beta',
  gamma => 'delta',
  epsilon => 'zeta',
};

$ ln -v alpha.txt tmp/beta.txt
tmp/beta.txt => alpha.txt

$ cat tmp/beta.txt
$class = {
  alpha => 'beta',
  gamma => 'delta',
  epsilon => 'zeta',
};
###

On Linux​:

###
$ perl -MFile​::Copy -e 'move "./alpha.txt" => "tmp/beta.txt" or die
"Unable to move​: $!";'

$ cat alpha.txt
$class = {
  alpha => 'beta',
  gamma => 'delta',
  epsilon => 'zeta',
};

$ cat tmp/beta.txt
$class = {
  alpha => 'beta',
  gamma => 'delta',
  epsilon => 'zeta',
};
###

Corroborates problem reported by original poster.

However, on Darwin ...

###
$ perl -MFile​::Copy -e 'move "./alpha.txt" => "tmp/beta.txt" or die
"Unable to move​: $!";'

$ cat alpha.txt
cat​: alpha.txt​: No such file or directory

$ cat tmp/beta.txt
$class = {
  alpha => 'beta',
  gamma => 'delta',
  epsilon => 'zeta',
};
###

... which does what I think original poster feels should happen.

Am I misunderstanding something about the problem -- or is this a
genuine difference between the two OSes?

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2011

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Nov 30, 2011

From schmorp@schmorp.de

On Tue, Nov 29, 2011 at 04​:27​:53PM -0800, James E Keenan via RT <perlbug-followup@​perl.org> wrote​:

To my surprise, I get different results on different OSes when I try to
reproduce this phenomenon. In my case, the two OSes are Linux and Darwin.

Just guessing, but thats probably because linux implements posix rename()
accurately, while some versions of os x are only posix-certified and far
from actually implementing it :)

The relevant posix spec section is, as I know nowadays​:

If the old argument and the new argument resolve to the same existing
file, rename() shall return successfully and perform no other action.

that is, if both old and new are hardlinks to the same file, rename just
does nothing, leaving both intact, reporting success. this is not a bug in
the posix spec either, it's really meant to act like that.

silly - one would expect rename to work on filenames.

In any case, since rename is "just" an optimiation, File​::Copy ought to
detect that (coreutils mv does it for example, at least when not posixly
correct). Maybe unlinking the from after a successfull rename might do the
trick - I'd rather not think too hard about it.

In any case, rename returning success on a posix system does not mean the
old name has been removed, and thats likely whats happening.

--
  The choice of a Deliantra, the free code+content MORPG
  -----==- _GNU_ http​://www.deliantra.net
  ----==-- _ generation
  ---==---(_)__ __ ____ __ Marc Lehmann
  --==---/ / _ \/ // /\ \/ / schmorp@​schmorp.de
  -=====/_/_//_/\_,_/ /_/\_\

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants