]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/attribs.c
- Fix mode change open in btape.c
[bacula/bacula] / bacula / src / findlib / attribs.c
1 /*
2  *  Encode and decode standard Unix attributes and
3  *   Extended attributes for Win32 and
4  *   other non-Unix systems, or Unix systems with ACLs, ...
5  *
6  *    Kern Sibbald, October MMII
7  *
8  *   Version $Id$
9  *
10  */
11 /*
12    Copyright (C) 2000-2005 Kern Sibbald
13
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License
16    version 2 as amended with additional clauses defined in the
17    file LICENSE in the main source directory.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
22    the file LICENSE for additional details.
23
24  */
25
26 #include "bacula.h"
27 #include "find.h"
28
29 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
30
31 #include "../lib/winapi.h"
32
33
34 /* Forward referenced subroutines */
35 static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd);
36 void unix_name_to_win32(POOLMEM **win32_name, char *name);
37 void win_error(JCR *jcr, char *prefix, POOLMEM *ofile);
38 HANDLE bget_handle(BFILE *bfd);
39 #endif
40
41 /* For old systems that don't have lchown() use chown() */
42 #ifndef HAVE_LCHOWN
43 #define lchown chown
44 #endif
45
46 /*=============================================================*/
47 /*                                                             */
48 /*             ***  A l l  S y s t e m s ***                   */
49 /*                                                             */
50 /*=============================================================*/
51
52 /*
53  * Return the data stream that will be used
54  */
55 int select_data_stream(FF_PKT *ff_pkt)
56 {
57    int stream;
58
59    /* Note, no sparse option for win32_data */
60    if (!is_portable_backup(&ff_pkt->bfd)) {
61       stream = STREAM_WIN32_DATA;
62       ff_pkt->flags &= ~FO_SPARSE;
63    } else if (ff_pkt->flags & FO_SPARSE) {
64       stream = STREAM_SPARSE_DATA;
65    } else {
66       stream = STREAM_FILE_DATA;
67    }
68 #ifdef HAVE_LIBZ
69    if (ff_pkt->flags & FO_GZIP) {
70       if (stream == STREAM_WIN32_DATA) {
71          stream = STREAM_WIN32_GZIP_DATA;
72       } else if (stream == STREAM_FILE_DATA) {
73          stream = STREAM_GZIP_DATA;
74       } else {
75          stream = STREAM_SPARSE_GZIP_DATA;
76       }
77    }
78 #endif
79    return stream;
80 }
81
82
83 /*
84  * Encode a stat structure into a base64 character string
85  *   All systems must create such a structure.
86  *   In addition, we tack on the LinkFI, which is non-zero in
87  *   the case of a hard linked file that has no data.  This
88  *   is a File Index pointing to the link that does have the
89  *   data (always the first one encountered in a save).
90  * You may piggyback attributes on this packet by encoding
91  *   them in the encode_attribsEx() subroutine, but this is
92  *   not recommended.
93  */
94 void encode_stat(char *buf, FF_PKT *ff_pkt, int data_stream)
95 {
96    char *p = buf;
97    struct stat *statp = &ff_pkt->statp;
98    /*
99     *  Encode a stat packet.  I should have done this more intelligently
100     *   with a length so that it could be easily expanded.
101     */
102    p += to_base64((int64_t)statp->st_dev, p);
103    *p++ = ' ';                        /* separate fields with a space */
104    p += to_base64((int64_t)statp->st_ino, p);
105    *p++ = ' ';
106    p += to_base64((int64_t)statp->st_mode, p);
107    *p++ = ' ';
108    p += to_base64((int64_t)statp->st_nlink, p);
109    *p++ = ' ';
110    p += to_base64((int64_t)statp->st_uid, p);
111    *p++ = ' ';
112    p += to_base64((int64_t)statp->st_gid, p);
113    *p++ = ' ';
114    p += to_base64((int64_t)statp->st_rdev, p);
115    *p++ = ' ';
116    p += to_base64((int64_t)statp->st_size, p);
117    *p++ = ' ';
118 #ifndef HAVE_MINGW
119    p += to_base64((int64_t)statp->st_blksize, p);
120    *p++ = ' ';
121    p += to_base64((int64_t)statp->st_blocks, p);
122    *p++ = ' ';
123 #else
124    p += to_base64((int64_t)0, p); /* output place holder */
125    *p++ = ' ';
126    p += to_base64((int64_t)0, p); /* output place holder */
127    *p++ = ' ';
128 #endif
129    p += to_base64((int64_t)statp->st_atime, p);
130    *p++ = ' ';
131    p += to_base64((int64_t)statp->st_mtime, p);
132    *p++ = ' ';
133    p += to_base64((int64_t)statp->st_ctime, p);
134    *p++ = ' ';
135    p += to_base64((int64_t)ff_pkt->LinkFI, p);
136    *p++ = ' ';
137
138 #ifdef HAVE_CHFLAGS
139    /* FreeBSD function */
140    p += to_base64((int64_t)statp->st_flags, p);  /* output st_flags */
141 #else
142    p += to_base64((int64_t)0, p);     /* output place holder */
143 #endif
144    *p++ = ' ';
145    p += to_base64((int64_t)data_stream, p);
146    *p = 0;
147    return;
148 }
149
150
151 /* Do casting according to unknown type to keep compiler happy */
152 #if !HAVE_GCC & HAVE_SUN_OS
153 #define plug(st, val) st = val        /* brain damaged compiler */
154 #else
155 template <class T> void plug(T &st, uint64_t val)
156     { st = static_cast<T>(val); }
157 #endif
158
159
160 /* Decode a stat packet from base64 characters */
161 int decode_stat(char *buf, struct stat *statp, int32_t *LinkFI)
162 {
163    char *p = buf;
164    int64_t val;
165
166    p += from_base64(&val, p);
167    plug(statp->st_dev, val);
168    p++;
169    p += from_base64(&val, p);
170    plug(statp->st_ino, val);
171    p++;
172    p += from_base64(&val, p);
173    plug(statp->st_mode, val);
174    p++;
175    p += from_base64(&val, p);
176    plug(statp->st_nlink, val);
177    p++;
178    p += from_base64(&val, p);
179    plug(statp->st_uid, val);
180    p++;
181    p += from_base64(&val, p);
182    plug(statp->st_gid, val);
183    p++;
184    p += from_base64(&val, p);
185    plug(statp->st_rdev, val);
186    p++;
187    p += from_base64(&val, p);
188    plug(statp->st_size, val);
189    p++;
190 #ifndef HAVE_MINGW
191    p += from_base64(&val, p);
192    plug(statp->st_blksize, val);
193    p++;
194    p += from_base64(&val, p);
195    plug(statp->st_blocks, val);
196    p++;
197 #else
198    p += from_base64(&val, p);
199 //   plug(statp->st_blksize, val);
200    p++;
201    p += from_base64(&val, p);
202 //   plug(statp->st_blocks, val);
203    p++;
204 #endif
205    p += from_base64(&val, p);
206    plug(statp->st_atime, val);
207    p++;
208    p += from_base64(&val, p);
209    plug(statp->st_mtime, val);
210    p++;
211    p += from_base64(&val, p);
212    plug(statp->st_ctime, val);
213
214    /* Optional FileIndex of hard linked file data */
215    if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
216       p++;
217       p += from_base64(&val, p);
218       *LinkFI = (uint32_t)val;
219    } else {
220       *LinkFI = 0;
221       return 0;
222    }
223
224    /* FreeBSD user flags */
225    if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
226       p++;
227       p += from_base64(&val, p);
228 #ifdef HAVE_CHFLAGS
229       plug(statp->st_flags, val);
230    } else {
231       statp->st_flags  = 0;
232 #endif
233    }
234
235    /* Look for data stream id */
236    if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
237       p++;
238       p += from_base64(&val, p);
239    } else {
240       val = 0;
241    }
242    return (int)val;
243 }
244
245 /* Decode a LinkFI field of encoded stat packet */
246 int32_t decode_LinkFI(char *buf, struct stat *statp)
247 {
248    char *p = buf;
249    int64_t val;
250
251    skip_nonspaces(&p);                /* st_dev */
252    p++;                               /* skip space */
253    skip_nonspaces(&p);                /* st_ino */
254    p++;
255    p += from_base64(&val, p);
256    plug(statp->st_mode, val);         /* st_mode */
257    p++;
258    skip_nonspaces(&p);                /* st_nlink */
259    p++;
260    skip_nonspaces(&p);                /* st_uid */
261    p++;
262    skip_nonspaces(&p);                /* st_gid */
263    p++;
264    skip_nonspaces(&p);                /* st_rdev */
265    p++;
266    skip_nonspaces(&p);                /* st_size */
267    p++;
268    skip_nonspaces(&p);                /* st_blksize */
269    p++;
270    skip_nonspaces(&p);                /* st_blocks */
271    p++;
272    skip_nonspaces(&p);                /* st_atime */
273    p++;
274    skip_nonspaces(&p);                /* st_mtime */
275    p++;
276    skip_nonspaces(&p);                /* st_ctime */
277
278    /* Optional FileIndex of hard linked file data */
279    if (*p == ' ' || (*p != 0 && *(p+1) == ' ')) {
280       p++;
281       p += from_base64(&val, p);
282       return (int32_t)val;
283    }
284    return 0;
285 }
286
287 /*
288  * Set file modes, permissions and times
289  *
290  *  fname is the original filename
291  *  ofile is the output filename (may be in a different directory)
292  *
293  * Returns:  true  on success
294  *           false on failure
295  */
296 bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
297 {
298    struct utimbuf ut;
299    mode_t old_mask;
300    bool ok = true;
301    off_t fsize;
302
303 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
304    if (attr->stream == STREAM_UNIX_ATTRIBUTES_EX &&
305        set_win32_attributes(jcr, attr, ofd)) {
306        if (is_bopen(ofd)) {
307            bclose(ofd);
308        }
309        pm_strcpy(attr->ofname, "*none*");
310        return true;
311    }
312    if (attr->data_stream == STREAM_WIN32_DATA ||
313        attr->data_stream == STREAM_WIN32_GZIP_DATA) {
314       if (is_bopen(ofd)) {
315          bclose(ofd);
316       }
317       pm_strcpy(attr->ofname, "*none*");
318       return true;
319    }
320
321
322    /*
323     * If Windows stuff failed, e.g. attempt to restore Unix file
324     *  to Windows, simply fall through and we will do it the
325     *  universal way.
326     */
327 #endif
328
329    old_mask = umask(0);
330    if (is_bopen(ofd)) {
331       char ec1[50], ec2[50];
332       fsize = blseek(ofd, 0, SEEK_END);
333       bclose(ofd);                    /* first close file */
334       if (fsize > 0 && fsize != (off_t)attr->statp.st_size) {
335          Jmsg3(jcr, M_ERROR, 0, _("File size of restored file %s not correct. Original %s, restored %s.\n"),
336             attr->ofname, edit_uint64(attr->statp.st_size, ec1),
337             edit_uint64(fsize, ec2));
338       }
339    }
340
341    ut.actime = attr->statp.st_atime;
342    ut.modtime = attr->statp.st_mtime;
343
344    /* ***FIXME**** optimize -- don't do if already correct */
345    /*
346     * For link, change owner of link using lchown, but don't
347     *   try to do a chmod as that will update the file behind it.
348     */
349    if (attr->type == FT_LNK) {
350       /* Change owner of link, not of real file */
351       if (lchown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
352          berrno be;
353          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
354             attr->ofname, be.strerror());
355          ok = false;
356       }
357    } else {
358       if (chown(attr->ofname, attr->statp.st_uid, attr->statp.st_gid) < 0) {
359          berrno be;
360          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file owner %s: ERR=%s\n"),
361             attr->ofname, be.strerror());
362          ok = false;
363       }
364       if (chmod(attr->ofname, attr->statp.st_mode) < 0) {
365          berrno be;
366          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file modes %s: ERR=%s\n"),
367             attr->ofname, be.strerror());
368          ok = false;
369       }
370
371       /*
372        * Reset file times.
373        */
374       if (utime(attr->ofname, &ut) < 0) {
375          berrno be;
376          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file times %s: ERR=%s\n"),
377             attr->ofname, be.strerror());
378          ok = false;
379       }
380 #ifdef HAVE_CHFLAGS
381       /*
382        * FreeBSD user flags
383        *
384        * Note, this should really be done before the utime() above,
385        *  but if the immutable bit is set, it will make the utimes()
386        *  fail.
387        */
388       if (chflags(attr->ofname, attr->statp.st_flags) < 0) {
389          berrno be;
390          Jmsg2(jcr, M_ERROR, 0, _("Unable to set file flags %s: ERR=%s\n"),
391             attr->ofname, be.strerror());
392          ok = false;
393       }
394 #endif
395    }
396    pm_strcpy(attr->ofname, "*none*");
397    umask(old_mask);
398    return ok;
399 }
400
401
402 /*=============================================================*/
403 /*                                                             */
404 /*                 * * *  U n i x * * * *                      */
405 /*                                                             */
406 /*=============================================================*/
407
408 #if !defined(HAVE_CYGWIN) && !defined(HAVE_WIN32)
409
410 /*
411  * It is possible to piggyback additional data e.g. ACLs on
412  *   the encode_stat() data by returning the extended attributes
413  *   here.  They must be "self-contained" (i.e. you keep track
414  *   of your own length), and they must be in ASCII string
415  *   format. Using this feature is not recommended.
416  * The code below shows how to return nothing.  See the Win32
417  *   code below for returning something in the attributes.
418  */
419 int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
420 {
421 #ifdef HAVE_DARWIN_OS
422    /*
423     * We save the Mac resource fork length so that on a
424     * restore, we can be sure we put back the whole resource.
425     */
426    char *p;
427    p = attribsEx;
428    if (ff_pkt->flags & FO_HFSPLUS) {
429       p += to_base64((uint64_t)(ff_pkt->hfsinfo.rsrclength), p);
430    }
431    *p = 0;
432 #else
433    *attribsEx = 0;                    /* no extended attributes */
434 #endif
435    return STREAM_UNIX_ATTRIBUTES;
436 }
437
438 #endif
439
440
441
442 /*=============================================================*/
443 /*                                                             */
444 /*                 * * *  W i n 3 2 * * * *                    */
445 /*                                                             */
446 /*=============================================================*/
447
448 #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32)
449
450 int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
451 {
452    char *p = attribsEx;
453    WIN32_FILE_ATTRIBUTE_DATA atts;
454    ULARGE_INTEGER li;
455
456    attribsEx[0] = 0;                  /* no extended attributes */
457
458    // try unicode version
459    if (p_GetFileAttributesExW)  {
460       unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
461
462       POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);   
463       UTF8_2_wchar(&pwszBuf, ff_pkt->sys_fname);
464
465       BOOL b=p_GetFileAttributesExW((LPCWSTR) pwszBuf, GetFileExInfoStandard, (LPVOID)&atts);
466       free_pool_memory(pwszBuf);
467
468       if (!b) {
469          win_error(jcr, "GetFileAttributesExW:", ff_pkt->sys_fname);
470          return STREAM_UNIX_ATTRIBUTES;
471       }
472    }
473    else {
474       if (!p_GetFileAttributesExA)
475          return STREAM_UNIX_ATTRIBUTES;
476
477       unix_name_to_win32(&ff_pkt->sys_fname, ff_pkt->fname);
478
479       if (!p_GetFileAttributesExA(ff_pkt->sys_fname, GetFileExInfoStandard,
480                               (LPVOID)&atts)) {
481          win_error(jcr, "GetFileAttributesExA:", ff_pkt->sys_fname);
482          return STREAM_UNIX_ATTRIBUTES;
483       }
484    }
485
486    p += to_base64((uint64_t)atts.dwFileAttributes, p);
487    *p++ = ' ';                        /* separate fields with a space */
488    li.LowPart = atts.ftCreationTime.dwLowDateTime;
489    li.HighPart = atts.ftCreationTime.dwHighDateTime;
490    p += to_base64((uint64_t)li.QuadPart, p);
491    *p++ = ' ';
492    li.LowPart = atts.ftLastAccessTime.dwLowDateTime;
493    li.HighPart = atts.ftLastAccessTime.dwHighDateTime;
494    p += to_base64((uint64_t)li.QuadPart, p);
495    *p++ = ' ';
496    li.LowPart = atts.ftLastWriteTime.dwLowDateTime;
497    li.HighPart = atts.ftLastWriteTime.dwHighDateTime;
498    p += to_base64((uint64_t)li.QuadPart, p);
499    *p++ = ' ';
500    p += to_base64((uint64_t)atts.nFileSizeHigh, p);
501    *p++ = ' ';
502    p += to_base64((uint64_t)atts.nFileSizeLow, p);
503    *p = 0;
504    return STREAM_UNIX_ATTRIBUTES_EX;
505 }
506
507 /* Define attributes that are legal to set with SetFileAttributes() */
508 #define SET_ATTRS ( \
509          FILE_ATTRIBUTE_ARCHIVE| \
510          FILE_ATTRIBUTE_HIDDEN| \
511          FILE_ATTRIBUTE_NORMAL| \
512          FILE_ATTRIBUTE_NOT_CONTENT_INDEXED| \
513          FILE_ATTRIBUTE_OFFLINE| \
514          FILE_ATTRIBUTE_READONLY| \
515          FILE_ATTRIBUTE_SYSTEM| \
516          FILE_ATTRIBUTE_TEMPORARY)
517
518
519 /*
520  * Set Extended File Attributes for Win32
521  *
522  *  fname is the original filename
523  *  ofile is the output filename (may be in a different directory)
524  *
525  * Returns:  true  on success
526  *           false on failure
527  */
528 static bool set_win32_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
529 {
530    char *p = attr->attrEx;
531    int64_t val;
532    WIN32_FILE_ATTRIBUTE_DATA atts;
533    ULARGE_INTEGER li;
534    POOLMEM *win32_ofile;
535
536    // if we have neither ansi nor wchar version, we leave
537    if (!(p_SetFileAttributesW || p_SetFileAttributesA))
538       return false;
539
540    if (!p || !*p) {                   /* we should have attributes */
541       Dmsg2(100, "Attributes missing. of=%s ofd=%d\n", attr->ofname, ofd->fid);
542       if (is_bopen(ofd)) {
543          bclose(ofd);
544       }
545       return false;
546    } else {
547       Dmsg2(100, "Attribs %s = %s\n", attr->ofname, attr->attrEx);
548    }
549
550    p += from_base64(&val, p);
551    plug(atts.dwFileAttributes, val);
552    p++;                               /* skip space */
553    p += from_base64(&val, p);
554    li.QuadPart = val;
555    atts.ftCreationTime.dwLowDateTime = li.LowPart;
556    atts.ftCreationTime.dwHighDateTime = li.HighPart;
557    p++;                               /* skip space */
558    p += from_base64(&val, p);
559    li.QuadPart = val;
560    atts.ftLastAccessTime.dwLowDateTime = li.LowPart;
561    atts.ftLastAccessTime.dwHighDateTime = li.HighPart;
562    p++;                               /* skip space */
563    p += from_base64(&val, p);
564    li.QuadPart = val;
565    atts.ftLastWriteTime.dwLowDateTime = li.LowPart;
566    atts.ftLastWriteTime.dwHighDateTime = li.HighPart;
567    p++;
568    p += from_base64(&val, p);
569    plug(atts.nFileSizeHigh, val);
570    p++;
571    p += from_base64(&val, p);
572    plug(atts.nFileSizeLow, val);
573
574    /* Convert to Windows path format */
575    win32_ofile = get_pool_memory(PM_FNAME);
576    unix_name_to_win32(&win32_ofile, attr->ofname);
577
578
579
580    /* At this point, we have reconstructed the WIN32_FILE_ATTRIBUTE_DATA pkt */
581
582    if (!is_bopen(ofd)) {
583       Dmsg1(100, "File not open: %s\n", attr->ofname);
584       bopen(ofd, attr->ofname, O_WRONLY|O_BINARY, 0);   /* attempt to open the file */
585    }
586
587    if (is_bopen(ofd)) {
588       Dmsg1(100, "SetFileTime %s\n", attr->ofname);
589       if (!SetFileTime(bget_handle(ofd),
590                          &atts.ftCreationTime,
591                          &atts.ftLastAccessTime,
592                          &atts.ftLastWriteTime)) {
593          win_error(jcr, "SetFileTime:", win32_ofile);
594       }
595       bclose(ofd);
596    }
597
598    Dmsg1(100, "SetFileAtts %s\n", attr->ofname);
599    if (!(atts.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) 
600    {
601       if (p_SetFileAttributesW) {
602          POOLMEM* pwszBuf = get_pool_memory (PM_FNAME);   
603          UTF8_2_wchar(&pwszBuf, win32_ofile);
604
605          BOOL b=p_SetFileAttributesW((LPCWSTR)pwszBuf, atts.dwFileAttributes & SET_ATTRS);
606          free_pool_memory(pwszBuf);
607       
608          if (!b) 
609             win_error(jcr, "SetFileAttributesW:", win32_ofile); 
610       }
611       else {
612          if (!p_SetFileAttributesA(win32_ofile, atts.dwFileAttributes & SET_ATTRS)) {
613             win_error(jcr, "SetFileAttributesA:", win32_ofile);
614          }
615       }
616    }
617    free_pool_memory(win32_ofile);
618    return true;
619 }
620
621 void win_error(JCR *jcr, char *prefix, POOLMEM *win32_ofile)
622 {
623    DWORD lerror = GetLastError();
624    LPTSTR msg;
625    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
626                  FORMAT_MESSAGE_FROM_SYSTEM,
627                  NULL,
628                  lerror,
629                  0,
630                  (LPTSTR)&msg,
631                  0,
632                  NULL);
633    Dmsg3(100, "Error in %s on file %s: ERR=%s\n", prefix, win32_ofile, msg);
634    strip_trailing_junk(msg);
635    Jmsg(jcr, M_ERROR, 0, _("Error in %s file %s: ERR=%s\n"), prefix, win32_ofile, msg);
636    LocalFree(msg);
637 }
638
639 void win_error(JCR *jcr, char *prefix, DWORD lerror)
640 {
641    LPTSTR msg;
642    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
643                  FORMAT_MESSAGE_FROM_SYSTEM,
644                  NULL,
645                  lerror,
646                  0,
647                  (LPTSTR)&msg,
648                  0,
649                  NULL);
650    strip_trailing_junk(msg);
651    if (jcr) {
652       Jmsg2(jcr, M_ERROR, 0, _("Error in %s: ERR=%s\n"), prefix, msg);
653    } else {
654       MessageBox(NULL, msg, prefix, MB_OK);
655    }
656    LocalFree(msg);
657 }
658
659
660 /* Conversion of a Unix filename to a Win32 filename */
661 extern void conv_unix_to_win32_path(const char *path, char *win32_path, DWORD dwSize);
662 void unix_name_to_win32(POOLMEM **win32_name, char *name)
663 {
664    /* One extra byte should suffice, but we double it */
665    /* add MAX_PATH bytes for VSS shadow copy name */
666    DWORD dwSize = 2*strlen(name)+MAX_PATH;
667    *win32_name = check_pool_memory_size(*win32_name, dwSize);
668    conv_unix_to_win32_path(name, *win32_name, dwSize);
669 }
670
671 #endif  /* HAVE_CYGWIN */