Recent

Author Topic: copyfile issue  (Read 1538 times)

michoux

  • Full Member
  • ***
  • Posts: 112
copyfile issue
« on: July 10, 2020, 02:30:13 pm »
Hello,

I am using copyfile procedure for a long time without problems.
In my latest project i use copyfile to copy a sqlite db file.
I can see that copyfile fails when this db file is opened from another app.
From windows I can still normally copy the file with copy/paste.
Is this normal behavior of copyfile? Any other suggestion?

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: copyfile issue
« Reply #1 on: July 10, 2020, 02:35:13 pm »

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: copyfile issue
« Reply #2 on: July 10, 2020, 02:41:48 pm »
Is this normal behavior of copyfile?
Yes, this is normal. FPC CopyFile opens the sourcefile with fmOpenRead or fmShareDenyWrite.
The fmShareDenyWrite prevents the writing of the file during the copy process.

From windows I can still normally copy the file with copy/paste.
Yes, but you can get a corrupt file if the file is written during the copy process. Unless Windows uses a shadow copy (in which case you have an old version).

Any other suggestion?
You could try the Windows api directly.

Code: Pascal  [Select][+][-]
  1. uses Windows;
  2.  
  3. procedure myCopyFile(SourcePathname, DestPathname: string);
  4. var
  5.   SourceArray, DestArray: array [0 .. 255] of Char; // Max length of path set at 80 chars
  6. begin // Doesn't support wildcards
  7.   StrPCopy(SourceArray, SourcePathname);
  8.   StrPCopy(DestArray, DestPathname);
  9.   Windows.CopyFile(SourceArray, DestArray, false); // Copies files even with 0 bytes
  10. end;

Another option (if Windows.CopyFile doesn't work) is to try SHFileOperation().
« Last Edit: July 10, 2020, 02:43:20 pm by rvk »

michoux

  • Full Member
  • ***
  • Posts: 112
Re: copyfile issue
« Reply #3 on: July 10, 2020, 03:06:57 pm »
Thank you for help.
Perhaps then the best would be to use backup option in sqlite.

rvk

  • Hero Member
  • *****
  • Posts: 6111
Re: copyfile issue
« Reply #4 on: July 10, 2020, 03:18:34 pm »
Thank you for help.
Perhaps then the best would be to use backup option in sqlite.
Yes. Using BackupSQL() could be a good option;

https://forum.lazarus.freepascal.org/index.php/topic,34533.msg226710.html#msg226710

Code: Pascal  [Select][+][-]
  1. uses
  2.   sqlite3backup;
  3.  
  4. procedure BackupSQL(Conn: TSQLite3Connection; FileName: string);
  5. var
  6.   f: string;
  7.   BK: TSQLite3Backup;
  8. begin
  9.   f := ChangeFileEXT(FileName, '') + ' [Backup ' + FormatDateTime('yyyy.mm.dd hh-nn-ss', Now) + '].sql';
  10.   BK := TSQLite3Backup.Create;
  11.   BK.Backup(Conn, f);
  12.   BK.Free;
  13. end;

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: copyfile issue
« Reply #5 on: July 10, 2020, 08:36:25 pm »
Code: Pascal  [Select][+][-]
  1. uses Windows;
  2. procedure myCopyFile(SourcePathname, DestPathname: string);
  3. var
  4.   SourceArray, DestArray: array [0 .. 255] of Char; // Max length of path set at 80 chars
  5. begin // Doesn't support wildcards
  6.   StrPCopy(SourceArray, SourcePathname);
  7.   StrPCopy(DestArray, DestPathname);
  8.   Windows.CopyFile(SourceArray, DestArray, false); // Copies files even with 0 bytes
  9. end;
Not a very good solution. The first is to make restrictions that the API function does not have (255 characters), and the second is to use the ANSI version.
Code: Pascal  [Select][+][-]
  1. function CopyFileAPI(const Source, Dest: string): Boolean;
  2. var
  3.   WSource, WDest: UnicodeString;
  4. begin
  5.   WSource := UTF8Decode(Source);
  6.   WDest := UTF8Decode(Dest);
  7.   Result := Windows.CopyFileW(Pointer(WSource), Pointer(WDest), False);
  8. end;

Thaddy

  • Hero Member
  • *****
  • Posts: 14204
  • Probably until I exterminate Putin.
Re: copyfile issue
« Reply #6 on: July 10, 2020, 08:50:59 pm »

Not a very good solution
Your solution is also not good enough,
Code: Pascal  [Select][+][-]
  1. function CopyFileAPI(const Source, Dest: unicodestring): Boolean;
  2. begin
  3.   Result := Windows.CopyFileW(PWidechar(Source), PWidechar(Dest), False);
  4. end;

and I am sure even that is not good enough.
Anyway the compiler does the conversion.
« Last Edit: July 10, 2020, 08:52:55 pm by Thaddy »
Specialize a type, not a var.

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: copyfile issue
« Reply #7 on: July 11, 2020, 05:04:57 am »
Anyway the compiler does the conversion.
Yes, only for each call, not once, as in my case. This is worse in terms of code size. Again the interface is different.
And more. PWideChar(S) is worse than Pointer(S), because the Windows API responds quite adequately to nil, but sometimes there are problems with a zero-length string.

 

TinyPortal © 2005-2018