// WriteBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple // tar file entries in order to collect all the alternate data streams for the file, it returns the next // tar file that was not processed, or io.EOF is there are no more. func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (*tar.Header, error) { bw := winio.NewBackupStreamWriter(w) var sd []byte var err error // Maintaining old SDDL-based behavior for backward compatibility. All new tar headers written // by this library will have raw binary for the security descriptor. if sddl, ok := hdr.Winheaders[hdrSecurityDescriptor]; ok { sd, err = winio.SddlToSecurityDescriptor(sddl) if err != nil { return nil, err } } if sdraw, ok := hdr.Winheaders[hdrRawSecurityDescriptor]; ok { sd, err = base64.StdEncoding.DecodeString(sdraw) if err != nil { return nil, err } } if len(sd) != 0 { bhdr := winio.BackupHeader{ Id: winio.BackupSecurity, Size: int64(len(sd)), } err := bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = bw.Write(sd) if err != nil { return nil, err } } if hdr.Typeflag == tar.TypeSymlink { _, isMountPoint := hdr.Winheaders[hdrMountPoint] rp := winio.ReparsePoint{ Target: filepath.FromSlash(hdr.Linkname), IsMountPoint: isMountPoint, } reparse := winio.EncodeReparsePoint(&rp) bhdr := winio.BackupHeader{ Id: winio.BackupReparseData, Size: int64(len(reparse)), } err := bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = bw.Write(reparse) if err != nil { return nil, err } } if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA { bhdr := winio.BackupHeader{ Id: winio.BackupData, Size: hdr.Size, } err := bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = io.Copy(bw, t) if err != nil { return nil, err } } // Copy all the alternate data streams and return the next non-ADS header. for { ahdr, err := t.Next() if err != nil { return nil, err } if ahdr.Typeflag != tar.TypeReg || !strings.HasPrefix(ahdr.Name, hdr.Name+":") { return ahdr, nil } bhdr := winio.BackupHeader{ Id: winio.BackupAlternateData, Size: ahdr.Size, Name: ahdr.Name[len(hdr.Name)+1:] + ":$DATA", } err = bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = io.Copy(bw, t) if err != nil { return nil, err } } }
// WriteBackupStreamFromTarFile writes a Win32 backup stream from the current tar file. Since this function may process multiple // tar file entries in order to collect all the alternate data streams for the file, it returns the next // tar file that was not processed, or io.EOF is there are no more. func WriteBackupStreamFromTarFile(w io.Writer, t *tar.Reader, hdr *tar.Header) (*tar.Header, error) { bw := winio.NewBackupStreamWriter(w) if sddl, ok := hdr.Winheaders[hdrSecurityDescriptor]; ok { sd, err := winio.SddlToSecurityDescriptor(sddl) if err != nil { return nil, err } bhdr := winio.BackupHeader{ Id: winio.BackupSecurity, Size: int64(len(sd)), } err = bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = bw.Write(sd) if err != nil { return nil, err } } if hdr.Typeflag == tar.TypeSymlink { _, isMountPoint := hdr.Winheaders[hdrMountPoint] rp := winio.ReparsePoint{ Target: hdr.Linkname, IsMountPoint: isMountPoint, } reparse := winio.EncodeReparsePoint(&rp) bhdr := winio.BackupHeader{ Id: winio.BackupReparseData, Size: int64(len(reparse)), } err := bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = bw.Write(reparse) if err != nil { return nil, err } } if hdr.Typeflag == tar.TypeReg || hdr.Typeflag == tar.TypeRegA { bhdr := winio.BackupHeader{ Id: winio.BackupData, Size: hdr.Size, } err := bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = io.Copy(bw, t) if err != nil { return nil, err } } // Copy all the alternate data streams and return the next non-ADS header. for { ahdr, err := t.Next() if err != nil { return nil, err } if ahdr.Typeflag != tar.TypeReg || !strings.HasPrefix(ahdr.Name, hdr.Name+":") { return ahdr, nil } bhdr := winio.BackupHeader{ Id: winio.BackupAlternateData, Size: ahdr.Size, Name: ahdr.Name[len(hdr.Name)+1:] + ":$DATA", } err = bw.WriteHeader(&bhdr) if err != nil { return nil, err } _, err = io.Copy(bw, t) if err != nil { return nil, err } } }