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