Re: Fix for 687151, gswin32 starts with 7s delay..., improved log message

Ray Johnston <[email protected]>
Newsgroups gmane.comp.printing.ghostscript.patches
Organization Artifex Software Inc.
Message-ID <[email protected]>
Igor and Alex.

Igor V. Melichev wrote:
>>Alex's analysis is not correct and the patch should not be
>>applied since it defeats access to network files on Windows
>>platforms.
> 
> 
> I'm not agree.
> The argument of 'filenameforall' MUST encode special
> characters with '\' escapes, and the implementation
> of 'filenameforall' MUST decode escapes.
> Alex found that we do not implement the decoding.
> Ray, are you agree with the latter, or not ?

I agree that filenameforall must remove the '\' escape
characters prior to sending the string to FindFirstFile.

That is not quite what Alex's patch did. If the input string
was C:\\fonts/* (entered into PostScript as (C:\\\\fonts/*) )
then Alex's patch was OK, but \lib/* looked in the /lib
path rather than the lib subdirectory of the current working
directory. This was a non-standard behaviour of the original
code also.

I believe all that is needed is to remove the '\' and pass
the next character through to the template for FindFirstFile.

I've attached a patch that accomplishes this based on the
patch from Alex, but with the simplified logic and better
comments.

> What should the user do if he does need to put a
> network path into a filenameforall argument ?
> Since a Windows network path MUST contain backslashes
> due to Windows syntax, the user MUST
> encode it with escapes, and our implementation MUST
> decode the escapes. I understand Alex's patch as
> doing the decoding.
> Ray, do you think my understanding isn't correct ?

No, you are correct. For example, on my system (with my
patch applied), from:

(\\\\\\\\192.168.2.100\\\\G/temp/*)
(template ') print dup =print (') =
{=} 100 string filenameforall

I get:

template '\\\\192.168.2.100\\G/temp/*'
\\192.168.2.100\G/temp/contrast.pdf
\\192.168.2.100\G/temp/Drafts
\\192.168.2.100\G/temp/x.py

>>The .generate_dir_list_templates is what is taking the valid
>>c:\gs/gs8.11/lib string (represented as a PS string as
>>(c:\\gs/gs8.12/lib) ) and turning it into the incorrect
>>c:\\gs/gs8.12/lib string -- in PostScript: (c:\\\\gs/gs8.12/lib)
> 
> 
> I'm not agree.
> .generate_dir_list_templates is done especially for
> encoding special characters for filenameforall,
> and the encoding happens correctly due to
> the 'filanameforall' argument semantics specified in PLRM.

I agree with you. I was incorrect about the .generate_dir_list_templates.
It is correct as stands.

Note that I also discovered a bug in the FONTPATH scanning that did
not correctly convert paths containing '\' characters as with:

   gswin32c -sFONTPATH=\Windows\Fonts

It worked before the patch only because it relied on the non-standard
behaviour of filenameforall which did not implement the '\' escape
character according to the PLRM.

The patch for gs_fonts.ps is also attached.

The Log message I will use on the commit is:

Fix incorrect handling of the '\' escape character in the filenameforall
implementation on Windwows. Fixes bug #687151. Also fix logic in the
.scanfontdir that relied on the incorrect filenameforall implementation.

DETAILS:
The previous NT filenameforall implementation did not translate the
template string to be used by the FindFirstFile Windows call. This
meant that the template was being passed the '\' escape characters
which were not correctly handled by the OS call.

Also testing -sFONTPATH=\Winnt\Fonts showed that this was also broken
in gs_fonts.ps since it didn't duplicate the '\' characters for the
template to filenameforall.

Note that other gp_* implementations of file enumeration don't
seem to handle escapes such as gp_unifs.c. The gp_macio.c doesn't
do anything, and the gp_dosfe.c (deprecated) seems totally broken.
The gp_os2.c appears to be a clone of the gp_ntfs.c, so should be
fixed. About the only version that seems to be handling the '\'
character according to the PLRM is gp_vms.c (can you believe that?).

Thanks to Alex Cherepanov and Igor Melichev for contributing.

---END LOG MESSAGE---

Regards,
Ray
_______________________________________________________________________
diff -c -w -r1.21 gp_ntfs.c
*** src/gp_ntfs.c       21 Oct 2003 11:54:04 -0000      1.21
--- src/gp_ntfs.c       10 Dec 2003 21:09:06 -0000
***************
*** 99,105 ****
                     file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern);

   /* Initialize an enumeration.  Note that * and ? in a directory */
! /* don't work, and \ is taken literally unless a second \ follows. */
   file_enum *
   gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t * mem)
   {
--- 99,106 ----
                     file_enum_enum_ptrs, file_enum_reloc_ptrs, pattern);

   /* Initialize an enumeration.  Note that * and ? in a directory */
! /* don't work with the OS call currently used. The '\' escape */
! /* character is removed for the 'Find...File' function.               */
   file_enum *
   gp_enumerate_files_init(const char *pat, uint patlen, gs_memory_t * mem)
   {
***************
*** 107,140 ****
       int pat_size = 2 * patlen + 1;
       char *pattern;
       int hsize = 0;
!     int i;

       if (pfen == 0)
         return 0;
-
       /* pattern could be allocated as a string, */
       /* but it's simpler for GC and freeing to allocate it as bytes. */
-
       pattern = (char *)gs_alloc_bytes(mem, pat_size,
                                      "gp_enumerate_files(pattern)");
       if (pattern == 0)
         return 0;
!     memcpy(pattern, pat, patlen);
!     /* find directory name = header */
!     for (i = 0; i < patlen; i++) {
!       switch (pat[i]) {
!           case '\\':
!               if (i + 1 < patlen && pat[i + 1] == '\\')
                     i++;
!               /* falls through */
!           case ':':
!           case '/':
!               hsize = i + 1;
         }
       }
!     pattern[patlen] = 0;
       pfen->pattern = pattern;
!     pfen->patlen = patlen;
       pfen->pat_size = pat_size;
       pfen->head_size = hsize;
       pfen->memory = mem;
--- 108,142 ----
       int pat_size = 2 * patlen + 1;
       char *pattern;
       int hsize = 0;
!     int i, j;

       if (pfen == 0)
         return 0;
       /* pattern could be allocated as a string, */
       /* but it's simpler for GC and freeing to allocate it as bytes. */
       pattern = (char *)gs_alloc_bytes(mem, pat_size,
                                      "gp_enumerate_files(pattern)");
       if (pattern == 0)
         return 0;
!     /* translate the template into a pattern discarding the escape  */
!     /* char '\' (not needed by the OS Find...File logic). Note that */
!     /* a final '\' in the string is also discarded.               */
!     for (i = 0, j=0; i < patlen; i++) {
!       if (pat[i] == '\\') {
             i++;
!           if (i == patlen)
!               break;          /* '\' at end ignored */
         }
+       pattern[j++]=pat[i];
+     }
+     /* Scan for last path separator to determine 'head_size' (directory part)
*/
+     for (i = 0; i < j; i++) {
+       if(pattern[i] == '/' || pattern[i] == '\\' || pattern[i] == ':')
+       hsize = i+1;
       }
!     pattern[j] = 0;
       pfen->pattern = pattern;
!     pfen->patlen = j;
       pfen->pat_size = pat_size;
       pfen->head_size = hsize;
       pfen->memory = mem;
________________________________________________________________________________
diff -c -r1.44 gs_fonts.ps
*** lib/gs_fonts.ps     1 Nov 2003 13:18:09 -0000       1.44
--- lib/gs_fonts.ps     10 Dec 2003 21:47:20 -0000
***************
*** 276,286 ****
   /.scanfontdir           % <dirname> .scanfontdir -
    { currentglobal exch true setglobal
      QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
!    (*) 1 index
!
!    .file_name_separator
!    dup (\\) eq { pop (\\\\) } if        % double \ for pattern match
!    concatstrings exch concatstrings
      0 0 0 4 -1 roll      % found scanned files
       {           % stack: <fontcount> <scancount> <filecount> <filename>
         exch 1 add exch                   % increment filecount
--- 276,282 ----
   /.scanfontdir           % <dirname> .scanfontdir -
    { currentglobal exch true setglobal
      QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if
!    [ 1 index ] (*) .generate_dir_list_templates
      0 0 0 4 -1 roll      % found scanned files
       {           % stack: <fontcount> <scancount> <filecount> <filename>
         exch 1 add exch                   % increment filecount
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.