static CopyFileResult CopyFileCallback(CopyFileWhat what, CopyFileStep stage, IntPtr state, string source, string target, IntPtr ctx) { // Console.WriteLine ("CopyFileCallback ({0}, {1}, 0x{2}, {3}, {4}, 0x{5})", what, stage, state.ToString ("x"), source, target, ctx.ToString ("x")); switch (what) { case CopyFileWhat.File: if (!IsUptodate(source, target)) { if (stage == CopyFileStep.Finish) { Driver.Log(1, "Copied {0} to {1}", source, target); } return(CopyFileResult.Continue); } else { Driver.Log(3, "Target '{0}' is up-to-date", target); return(CopyFileResult.Skip); } case CopyFileWhat.Dir: case CopyFileWhat.DirCleanup: case CopyFileWhat.CopyData: case CopyFileWhat.CopyXattr: return(CopyFileResult.Continue); case CopyFileWhat.Error: throw ErrorHelper.CreateError(1021, "Could not copy the file '{0}' to '{1}': {2}", source, target, Target.strerror(Marshal.GetLastWin32Error())); default: return(CopyFileResult.Continue); } }
public static void UpdateDirectory(string source, string target) { if (!Directory.Exists(target)) { Directory.CreateDirectory(target); } // Mono's File.Copy can't handle symlinks (the symlinks are followed instead of copied), // so we need to use native functions directly. Luckily OSX provides exactly what we need. IntPtr state = copyfile_state_alloc(); try { CopyFileCallbackDelegate del = CopyFileCallback; copyfile_state_set(state, CopyFileState.StatusCB, Marshal.GetFunctionPointerForDelegate(del)); int rv = copyfile(source, target, state, CopyFileFlags.Data | CopyFileFlags.Recursive | CopyFileFlags.Nofollow); if (rv != 0) { throw ErrorHelper.CreateError(1022, "Could not copy the directory '{0}' to '{1}': {2}", source, target, Target.strerror(Marshal.GetLastWin32Error())); } } finally { copyfile_state_free(state); } }