From 15414d2b8179f5759172a843e63bd4f4857b021d Mon Sep 17 00:00:00 2001 From: Reini Urban Date: Sat, 7 Jul 2007 17:00:54 +0200 Subject: [PATCH] cygwin path conversions, take 4 From: "Reini Urban" Message-ID: <6910a60707070600xa8638eak3c3f20b20ccc093a@mail.gmail.com> p4raw-id: //depot/perl@31568 --- README.cygwin | 54 ++++++++++++++++++++++++------ cygwin/cygwin.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- t/lib/cygwin.t | 14 +++++++- 3 files changed, 155 insertions(+), 14 deletions(-) diff --git a/README.cygwin b/README.cygwin index 8940ca6..d618b9d 100644 --- a/README.cygwin +++ b/README.cygwin @@ -27,11 +27,11 @@ platforms. They run thanks to the Cygwin library which provides the UNIX system calls and environment these programs expect. More information about this project can be found at: - http://www.cygwin.com/ + F A recent net or commercial release of Cygwin is required. -At the time this document was last updated, Cygwin 1.5.2 was current. +At the time this document was last updated, Cygwin 1.5.24 was current. =head2 Cygwin Configuration @@ -143,9 +143,10 @@ NOTE: The GDBM library only works on NTFS partitions. BerkeleyDB is available for Cygwin. -NOTE: The BerkeleyDB library only completely works on NTFS partitions. +NOTE: The BerkeleyDB library only completely works on NTFS partitions +and db-4.3 is flawed. -=item * C<-lcygipc> (C) +=item * C (C) A port of SysV IPC is available for Cygwin. @@ -292,7 +293,7 @@ directory (where you said to put public executables). It does not wait until the C process to install the I script, this is because the remainder of the C refers to I without fully specifying its path and does this from multiple subdirectories. -The assumption is that $installbin is in your current C. If this +The assumption is that I<$installbin> is in your current C. If this is not the case C will fail at some point. If this happens, just manually copy I from the source directory to somewhere in your C. @@ -303,7 +304,7 @@ There are two steps to running the test suite: make test 2>&1 | tee log.make-test - cd t;./perl harness 2>&1 | tee ../log.harness + cd t; ./perl harness 2>&1 | tee ../log.harness The same tests are run both times, but more information is provided when running as C<./perl harness>. @@ -323,8 +324,8 @@ user write bit (files are always readable, files are executable if they have a F<.{com,bat,exe}> extension or begin with C<#!>, directories are always readable and executable). On WinNT with the I C setting, the additional mode bits are stored as extended file attributes. -On WinNT with the I C setting, permissions use the standard -WinNT security descriptors and access control lists. Without one of +On WinNT with the default I C setting, permissions use the +standard WinNT security descriptors and access control lists. Without one of these options, these tests will fail (listing not updated yet): Failed Test List of failed @@ -356,7 +357,7 @@ If you intend to run only on FAT (or if using AnyDBM_File on FAT), run Configure with the -Ui_ndbm and -Ui_dbm options to prevent NDBM_File and ODBM_File being built. -With NTFS (and CYGWIN=ntsec), there should be no problems even if +With NTFS (and no CYGWIN=nontsec), there should be no problems even if perl was built on FAT. =head2 C failures in io_* tests @@ -395,12 +396,21 @@ File names are case insensitive, but case preserving. A pathname that contains a backslash or drive letter is a Win32 pathname (and not subject to the translations applied to POSIX style pathnames). +For conversion we have C and +C. + +Pathnames may not contain Unicode characters. C still uses the +ANSI API calls and no Unicode calls because of newlib deficiencies. +There's an unofficial unicode patch for cygwin at +F + =item * Text/Binary When a file is opened it is in either text or binary mode. In text mode a file is subject to CR/LF/Ctrl-Z translations. With Cygwin, the default mode for an C is determined by the mode of the mount that underlies -the file. Perl provides a C function to set binary mode on files +the file. See C and C. +Perl provides a C function to set binary mode on files that otherwise would be treated as text. C with the C flag sets text mode on files that otherwise would be treated as binary: @@ -487,7 +497,7 @@ F to install it and run rebaseall. =item C -Returns current working directory. +Returns the current working directory. =item C @@ -498,6 +508,28 @@ may not be the same). Translates a Windows pid to the corresponding cygwin pid (if any). +=item C + +Translates a Windows path to the corresponding cygwin path respecting +the current mount points. With a second non-null argument returns an +absolute path. Double-byte characters will not be translated. + +=item C + +Translates a cygwin path to the corresponding cygwin path respecting +the current mount points. With a second non-null argument returns an +absolute path. Double-byte characters will not be translated. + +=item C + +Returns true if the given cygwin path is binary mounted, false if the +path is mounted in textmode. + +=item C + +Returns true if the given cygwin path is mounted in textmode (C<"\r\n"> C=C C<"\n">), +false if the path is mounted binary. The result is complementary to C. + =back =head1 INSTALL PERL ON CYGWIN diff --git a/cygwin/cygwin.c b/cygwin/cygwin.c index 2f6e224..57f3b6a 100644 --- a/cygwin/cygwin.c +++ b/cygwin/cygwin.c @@ -193,6 +193,99 @@ XS(XS_Cygwin_winpid_to_pid) XSRETURN_UNDEF; } +XS(XS_Cygwin_win_to_posix_path) +{ + dXSARGS; + int absolute_flag = 0; + STRLEN len; + int err; + char *pathname, *buf; + + if (items < 1 || items > 2) + Perl_croak(aTHX_ "Usage: Cygwin::win_to_posix_path(pathname, [absolute])"); + + pathname = SvPV(ST(0), len); + if (items == 2) + absolute_flag = SvTRUE(ST(1)); + + if (!len) + Perl_croak(aTHX_ "can't convert empty path"); + buf = (char *) safemalloc (len + 260 + 1001); + + if (absolute_flag) + err = cygwin_conv_to_full_posix_path(pathname, buf); + else + err = cygwin_conv_to_posix_path(pathname, buf); + if (!err) { + ST(0) = sv_2mortal(newSVpv(buf, 0)); + safefree(buf); + XSRETURN(1); + } else { + safefree(buf); + XSRETURN_UNDEF; + } +} + +XS(XS_Cygwin_posix_to_win_path) +{ + dXSARGS; + int absolute_flag = 0; + STRLEN len; + int err; + char *pathname, *buf; + + if (items < 1 || items > 2) + Perl_croak(aTHX_ "Usage: Cygwin::posix_to_win_path(pathname, [absolute])"); + + pathname = SvPV(ST(0), len); + if (items == 2) + absolute_flag = SvTRUE(ST(1)); + + if (!len) + Perl_croak(aTHX_ "can't convert empty path"); + buf = (char *) safemalloc(len + 260 + 1001); + + if (absolute_flag) + err = cygwin_conv_to_full_win32_path(pathname, buf); + else + err = cygwin_conv_to_win32_path(pathname, buf); + if (!err) { + ST(0) = sv_2mortal(newSVpv(buf, 0)); + safefree(buf); + XSRETURN(1); + } else { + safefree(buf); + XSRETURN_UNDEF; + } +} + +XS(XS_Cygwin_is_binmount) +{ + dXSARGS; + char *pathname; + + if (items != 1) + Perl_croak(aTHX_ "Usage: Cygwin::is_binmount(pathname)"); + + pathname = SvPV_nolen(ST(0)); + + ST(0) = boolSV(cygwin_internal(CW_GET_BINMODE, pathname)); + XSRETURN(1); +} + +XS(XS_Cygwin_is_textmount) +{ + dXSARGS; + char *pathname; + + if (items != 1) + Perl_croak(aTHX_ "Usage: Cygwin::is_textmount(pathname)"); + + pathname = SvPV_nolen(ST(0)); + + ST(0) = boolSV(!cygwin_internal(CW_GET_BINMODE, pathname)); + XSRETURN(1); +} void init_os_extras(void) @@ -202,8 +295,12 @@ init_os_extras(void) void *handle; newXS("Cwd::cwd", Cygwin_cwd, file); - newXS("Cygwin::winpid_to_pid", XS_Cygwin_winpid_to_pid, file); - newXS("Cygwin::pid_to_winpid", XS_Cygwin_pid_to_winpid, file); + newXSproto("Cygwin::winpid_to_pid", XS_Cygwin_winpid_to_pid, file, "$"); + newXSproto("Cygwin::pid_to_winpid", XS_Cygwin_pid_to_winpid, file, "$"); + newXSproto("Cygwin::win_to_posix_path", XS_Cygwin_win_to_posix_path, file, "$;$"); + newXSproto("Cygwin::posix_to_win_path", XS_Cygwin_posix_to_win_path, file, "$;$"); + newXSproto("Cygwin::is_binmount", XS_Cygwin_is_binmount, file, "$"); + newXSproto("Cygwin::is_textmount", XS_Cygwin_is_textmount, file, "$"); /* Initialize Win32CORE if it has been statically linked. */ handle = dlopen(NULL, RTLD_LAZY); diff --git a/t/lib/cygwin.t b/t/lib/cygwin.t index 0148546..18ada21 100644 --- a/t/lib/cygwin.t +++ b/t/lib/cygwin.t @@ -9,7 +9,7 @@ BEGIN { } } -use Test::More tests => 4; +use Test::More tests => 8; is(Cygwin::winpid_to_pid(Cygwin::pid_to_winpid($$)), $$, "perl pid translates to itself"); @@ -29,3 +29,15 @@ close($ps); is(Cygwin::winpid_to_pid($catwinpid), $catpid, "winpid to pid"); is(Cygwin::pid_to_winpid($catpid), $catwinpid, "pid to winpid"); close($cat); + +is(Cygwin::win_to_posix_path("t\\lib"), "t/lib", "win to posix path: t/lib"); +is(Cygwin::posix_to_win_path("t/lib"), "t\\lib", "posix to win path: t\\lib"); + +use Win32; +use Cwd; +$pwd = getcwd(); +chdir("/"); +$winpath = Win32::GetCwd(); +is(Cygwin::posix_to_win_path("/", 1), $winpath, "posix to absolute win path"); +chdir($pwd); +is(Cygwin::win_to_posix_path($winpath, 1), "/", "win to absolute posix path"); -- 2.7.4