title: Extracting .tar.gz using libarchive on UNC path?
body: <p>I'm trying to use <code>libarchive</code> to extract <code>.tar.gz</code> file to current folder. Test machine if win7 64bit running under virtual box. It works fine if I do it in <code>C:\</code> (<code>.vdi</code> disk), however it fails on <code>E:\</code> (shared folder from host). Based on this</p>
  
  <pre><code>Can't create '\\?\e:\folder\file'
  </code></pre>
  
  <p>error message I assume the issue is UNC path. Is it possible to handle it with <code>libarchive</code>?</p>
  
  <p>Here is my code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;cstdio&gt;
  #include &lt;stdexcept&gt;
  
  #include &lt;archive.h&gt;
  #include &lt;archive_entry.h&gt;
  
  #include "utils.h"
  
  int copy_data(struct archive * ar, struct archive * aw) {
      int r;
      size_t size;
      const void *buff;
      int64_t offset;
  
      for (;;) {
          r = archive_read_data_block(ar, &amp;buff, &amp;size, &amp;offset);
          if (r == ARCHIVE_EOF) {
              return (ARCHIVE_OK);
          } else if (r &lt; ARCHIVE_OK) {
              return (r);
          }
          r = archive_write_data_block(aw, buff, size, offset);
          if (r &lt; ARCHIVE_OK) {
              std::cerr &lt;&lt; archive_error_string(aw) &lt;&lt; std::endl;
              return (r);
          }
      }
  }
  
  void handle_errors(archive * a, int r, const char * msg) {
      if (r &lt; ARCHIVE_OK) {
          std::cerr &lt;&lt; archive_error_string(a) &lt;&lt; std::endl;
      }
      if (r &lt; ARCHIVE_WARN) {
          throw std::runtime_error(msg);
      }
  };
  
  void extract(std::string target_file_name) {
      struct archive * a = nullptr;
      struct archive * ext = nullptr;
      struct archive_entry * entry = nullptr;
      int flags, r;
  
      /* Select which attributes we want to restore. */
      flags = ARCHIVE_EXTRACT_TIME;
      flags |= ARCHIVE_EXTRACT_UNLINK;
      flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT;
  
      a = archive_read_new();
      if (!a) { throw std::runtime_error("Cannot archive_read_new"); }
      On_Scope_Exit([&amp;] { archive_read_free(a); });
      archive_read_support_format_tar(a);
      archive_read_support_filter_gzip(a);
  
      ext = archive_write_disk_new();
      if (!ext) { throw std::runtime_error("Cannot archive_write_disk_new"); }
      On_Scope_Exit([&amp;] { archive_write_close(ext); archive_write_free(ext); });
      archive_write_disk_set_options(ext, flags);
      archive_write_disk_set_standard_lookup(ext);
  
      if ((r = archive_read_open_filename(a, target_file_name.c_str(), 10240))) {
          throw std::runtime_error("Cannot archive_read_open_filename");
      }
      On_Scope_Exit([&amp;] { archive_read_close(a); });
  
      for (;;) {
          r = archive_read_next_header(a, &amp;entry);
          if (r == ARCHIVE_EOF) {
              break;
          }
          handle_errors(a, r, "Encountered error while reading header.");
          r = archive_write_header(ext, entry);
          if (r &lt; ARCHIVE_OK) {
              std::cerr &lt;&lt; archive_error_string(ext) &lt;&lt; std::endl;
          }
          else if (archive_entry_size(entry) &gt; 0) {
              r = copy_data(a, ext);
              handle_errors(ext, r, "Encountered error while copy data.");
          }
          r = archive_write_finish_entry(ext);
          handle_errors(ext, r, "Encountered error while finishing entry.");
      }
  }
  
  int main(int, char**) {
      try {
          std::string tmp_file_name = "file.tar.gz";
          extract(tmp_file_name);
          return 0;
      } catch (std::exception &amp; e) {
          std::cerr &lt;&lt; e.what() &lt;&lt; std::endl;
          return 1;
      }
  }
  </code></pre>
  
  <p>I guess I could use <a href="https://stackoverflow.com/a/2324777/781743">https://stackoverflow.com/a/2324777/781743</a> and chdir to non-unc path first (if it exists), that should work? But is there a way to make <code>libarchive</code> support <code>UNC</code> paths directly?</p>