bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Building sharutils 4.13.4 with MinGW


From: Eli Zaretskii
Subject: Re: Building sharutils 4.13.4 with MinGW
Date: Tue, 09 Apr 2013 19:21:38 +0300

> Date: Mon, 08 Apr 2013 18:35:45 +0300
> From: Eli Zaretskii <address@hidden>
> Cc: address@hidden, address@hidden
> 
> > Date: Sun, 07 Apr 2013 13:46:00 -0700
> > From: Bruce Korb <address@hidden>
> > CC: address@hidden, address@hidden, 
> >  Andreas Schwab <address@hidden>
> > 
> > >     For the other errors: I wrote emulations for fork (always fails),
> > >     wait (always fails) and pipe (calls _pipe), and also add getuid,
> > >     getpwnam and getgrnam to idcache.c.  However, I think gnulib has
> > >     replacements for at least some of these functions.
> > 
> > Not that I can find.
> > > $ list=$(find * -type f)
> > > $ fgrep getuid $list
> > > $ fgrep getpwnam $list
> > > $ fgrep getgrnam $list
> > > $ echo "$list"|egrep "getuid|getpwnam|getgrnam"
> > > $
> 
> I meant fork, wait (waitpid in gnulib), and pipe.

Anyway, I hate it when programs lose features as result of porting
them.  So the changes below resurrect the full strength of 'shar' even
when 'fork' is not available.  The trick is to use shell pipes
instead.

With these changes, all the tests in v4.13.4 pass, with a single
exception: shar-1, and that failure is not a real one:

     + ./shar-1
     *** shar-1-7252.sample     Tue Apr  9 13:17:07 2013
     --- shar-1-7252.outf       Tue Apr  9 13:17:07 2013
     ***************
     *** 12,18 ****
       # This shar contains:
       # length mode       name
       # ------ ---------- ------------------------------------------
     ! #     51 -rw-r--r-- shar-1.in
       #
       MD5SUM=${MD5SUM-md5sum}
       f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
     --- 12,18 ----
       # This shar contains:
       # length mode       name
       # ------ ---------- ------------------------------------------
     ! #     51 -rw-rw-rw- shar-1.in
       #
       MD5SUM=${MD5SUM-md5sum}
       f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`
     ***************
     *** 125,131 ****
       SHAR_EOF
         (set <date> 'shar-1.in'
          eval "${shar_touch}") && \
     !   chmod 0644 'shar-1.in'
       if test $? -ne 0
       then ${echo} "restore of shar-1.in failed"
       fi
     --- 125,131 ----
       SHAR_EOF
         (set <date> 'shar-1.in'
          eval "${shar_touch}") && \
     !   chmod 0666 'shar-1.in'
       if test $? -ne 0
       then ${echo} "restore of shar-1.in failed"
       fi

IOW, it "fails" because mode bits for group and other do not match,
which is expected on Windows.

Here are the changes:


--- src/shar.c~3        2013-04-09 13:37:23.287005000 +0300
+++ src/shar.c  2013-04-09 13:45:18.562796500 +0300
@@ -173,7 +173,20 @@ typedef struct {
 
 compact_state_t gzip_compaction = {
   .cmpr_name    = "gzip",
+#if HAVE_WORKING_FORK
   .cmpr_cmd_fmt = "gzip -c -%u < %s",
+#else
+  /* When 'fork' is unavailable, we use shell pipes instead, and
+     delegate the encoding to uuencode.  MinGW needs special quoting,
+     while Posix systems use a quoted file name produced by quotearg.
+     Also, avoid redirection for MinGW, since Windows shells cannot
+     redirect from files with Unix-style forward slashes.  */
+#ifdef __MINGW32__
+  .cmpr_cmd_fmt = "gzip -c -%u \"%s\" | uuencode \"%s\"",
+#else
+  .cmpr_cmd_fmt = "gzip -c -%u < %s | uuencode %s",
+#endif
+#endif
   .cmpr_title   = "gzipped",
   .cmpr_mode    = "gzi",
   .cmpr_unpack  = "gzip -d < ${lock_dir}/gzi > %s && \\\n",
@@ -182,7 +195,15 @@ compact_state_t gzip_compaction = {
 
 compact_state_t xz_compaction = {
   .cmpr_name    = "xz",
+#if HAVE_WORKING_FORK
   .cmpr_cmd_fmt = "xz -z -c -%u < %s",
+#else
+#ifdef __MINGW32__
+  .cmpr_cmd_fmt = "xz -z -c -%u \"%s\" | uuencode \"%s\"",
+#else
+  .cmpr_cmd_fmt = "xz -z -c -%u < %s | uuencode %s",
+#endif
+#endif
   .cmpr_title   = "xz-compressed",
   .cmpr_mode    = "xzi",
   .cmpr_unpack  = "xz --decompress < ${lock_dir}/xzi > %s && \\\n",
@@ -191,7 +212,15 @@ compact_state_t xz_compaction = {
 
 compact_state_t bzip2_compaction = {
   .cmpr_name    = "bzip2",
+#if HAVE_WORKING_FORK
   .cmpr_cmd_fmt = "bzip2 -z -c -%u < %s",
+#else
+#ifdef __MINGW32__
+  .cmpr_cmd_fmt = "bzip2 -z -c -%u \"%s\" | uuencode \"%s\"",
+#else
+  .cmpr_cmd_fmt = "bzip2 -z -c -%u < %s | uuencode %s",
+#endif
+#endif
   .cmpr_title   = "bzipped",
   .cmpr_mode    = "bzi",
   .cmpr_unpack  = "bzip2 -d < ${lock_dir}/bzi > %s && \\\n",
@@ -201,7 +230,15 @@ compact_state_t bzip2_compaction = {
 #ifdef HAVE_COMPRESS
 compact_state_t compress_compaction = {
   .cmpr_name    = "compress",
+#if HAVE_WORKING_FORK
   .cmpr_cmd_fmt = "compress -b%u < %s",
+#else
+#ifdef __MINGW32__
+  .cmpr_cmd_fmt = "compress -b%u \"%s\" | uuencode \"%s\"",
+#else
+  .cmpr_cmd_fmt = "compress -b%u < %s | uuencode %s",
+#endif
+#endif
   .cmpr_title   = "compressed",
   .cmpr_mode    = "cmp",
   .cmpr_unpack  = "compress -d < ${lock_dir}/cmp > %s && \\\n",
@@ -1270,6 +1307,8 @@ file_needs_encoding (char const * fname)
 #undef BYTE_IS_BINARY
 }
 
+#if HAVE_WORKING_FORK
+
 static void
 encode_file_to_pipe (
      int out_fd,
@@ -1315,6 +1354,71 @@ encode_file_to_pipe (
   exit (EXIT_SUCCESS);
 }
 
+#else  /* !HAVE_WORKING_FORK */
+
+static FILE *
+compress_and_encode_file (
+     const char *  local_name,
+     const char *  q_local_name,
+     const char *  restore_name)
+{
+  /* Start writing the pipe with encodes.  */
+
+  FILE * in_fp;
+  char * cmdline;
+  /* A command to use for encoding an uncompressed text file.  */
+#ifdef __MINGW32__
+  static char uu_cmd_fmt[] = "uuencode \"%s\" \"%s\"";
+#else
+  static char uu_cmd_fmt[] = "uuencode %s %s";
+#endif
+
+  if (cmpr_state != NULL)
+    {
+      /* 2 * strlen (restore_name) to allow for quoting.  */
+      cmdline = alloca (strlen (q_local_name) + 2 * strlen (restore_name)
+                        + strlen (cmpr_state->cmpr_cmd_fmt)
+                        /* 10 for compression level, 1 for null.  */
+                        + 10 + 1);
+      /* See commentary for gzip_compaction above, for the reasons why
+         MinGW uses a slightly different command in the pipe.  */
+#ifdef __MINGW32__
+      sprintf (cmdline, cmpr_state->cmpr_cmd_fmt,
+               cmpr_state->cmpr_level, local_name, restore_name);
+#else
+      sprintf (cmdline, cmpr_state->cmpr_cmd_fmt,
+               cmpr_state->cmpr_level, q_local_name,
+               quotearg_n_style (QUOT_ID_RNAME, shell_always_quoting_style,
+                                 restore_name));
+#endif
+    }
+  else
+    {
+      cmdline = alloca (strlen (q_local_name) + 2 * strlen (restore_name)
+                        + strlen (uu_cmd_fmt)
+                        /* 10 for compression level, 1 for null.  */
+                        + 10 + 1);
+#ifdef __MINGW32__
+      sprintf (cmdline, uu_cmd_fmt, local_name, restore_name);
+#else
+      sprintf (cmdline, uu_cmd_fmt, q_local_name,
+               quotearg_n_style (QUOT_ID_RNAME, shell_always_quoting_style,
+                                 restore_name));
+#endif
+    }
+  /* Don't use freadonly_mode because it might be "rb", while we need
+     text-mode read here, because we will be reading pure text from
+     uuencode, and we want to drop any CR characters from the CRLF
+     line endings, when we write the result into the shar.  */
+  in_fp = popen (cmdline, "r");
+
+  if (in_fp == NULL)
+    fserr (SHAR_EXIT_FAILED, "popen", cmdline);
+
+  return in_fp;
+}
+#endif  /* !HAVE_WORKING_FORK */
+
 #ifdef __MINGW32__
 int
 isatty (int fd)
@@ -1330,7 +1434,8 @@ open_shar_input (
      const char *  restore_name,
      const char *  q_restore_name,
      const char ** file_type_p,
-     const char ** file_type_remote_p)
+     const char ** file_type_remote_p,
+     int *pipe_p)
 {
   FILE * infp;
 
@@ -1348,6 +1453,7 @@ open_shar_input (
       infp = fopen (local_name, freadonly_mode);
       if (infp == NULL)
         fserr (SHAR_EXIT_FAILED, "fopen", local_name);
+      *pipe_p = 0;
     }
   else
     {
@@ -1356,6 +1462,7 @@ open_shar_input (
       *file_type_p        = cmpr_state ? cmpr_state->cmpr_title : _("text");
       *file_type_remote_p = cmpr_state ? cmpr_state->cmpr_title : _("(text)");
 
+#if HAVE_WORKING_FORK
       /* Fork a uuencode process.  */
 
       if (pipe (pipex) < 0)
@@ -1381,6 +1488,10 @@ open_shar_input (
           if (infp == NULL)
             fserr (SHAR_EXIT_FAILED, "fdopen", _("pipe[1]"));
         }
+#else  /* !HAVE_WORKING_FORK */
+      infp = compress_and_encode_file (local_name, q_local_name, restore_name);
+#endif
+      *pipe_p = 1;
     }
 
   return infp;
@@ -1579,7 +1690,7 @@ process_shar_input (FILE * input, off_t 
 
 static int
 start_sharing_file (char const ** lnameq_p, char const ** rnameq_p,
-                    FILE ** fpp, off_t * size_left_p)
+                    FILE ** fpp, off_t * size_left_p, int *pipe_p)
 {
   char const * lname = *lnameq_p;
   char const * rname = *rnameq_p;
@@ -1645,7 +1756,7 @@ start_sharing_file (char const ** lnameq
   else
     {
       *fpp = open_shar_input (lname, *lnameq_p, rname, *rnameq_p,
-                               &file_type, &file_type_remote);
+                              &file_type, &file_type_remote, pipe_p);
       if (*fpp == NULL)
         return 0;
     }
@@ -1777,8 +1888,9 @@ shar (const char * lname, const char * r
   int    split_flag = 0;          /* file split flag */
   char const * lname_q = lname;
   char const * rname_q = rname;
+  int pipe_p;                     /* opened directly or via a pipe */
 
-  if (! start_sharing_file (&lname_q, &rname_q, &input, &size_left))
+  if (! start_sharing_file (&lname_q, &rname_q, &input, &size_left, &pipe_p))
     return SHAR_EXIT_FAILED;
 
   if (struct_stat.st_size == 0)
@@ -1815,9 +1927,18 @@ shar (const char * lname, const char * r
 
       process_shar_input (input, &size_left, &split_flag, rname, rname_q);
 
-      fclose (input);
-      while (wait (NULL) >= 0)
-       ;
+      if (!pipe_p)
+        fclose (input);
+      else
+        {
+#if HAVE_WORKING_FORK
+          while (wait (NULL) >= 0)
+            ;
+#else
+          if (pclose (input))
+            fserr (SHAR_EXIT_FAILED, _("call"), "pclose");
+        }
+#endif
 
       fprintf (output, "%s\n", OPT_ARG(HERE_DELIMITER));
       if (split_flag && ! HAVE_OPT(QUIET_UNSHAR))
@@ -1935,6 +2056,9 @@ open_output (void)
   if (! HAVE_OPT(OUTPUT_PREFIX))
     {
       output = stdout;
+#ifdef __MINGW32__
+      _setmode (fileno (stdout) , _O_BINARY);
+#endif
       return;
     }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]