1{%MainUnit lazfileutils.pas} 2 3function FilenameIsAbsolute(const TheFilename: string):boolean; 4begin 5 Result:=FilenameIsUnixAbsolute(TheFilename); 6end; 7 8function FileOpenUTF8(const FileName: string; Mode: Integer): THandle; 9begin 10 Result := SysUtils.FileOpen(UTF8ToSys(FileName), Mode); 11end; 12 13function FileCreateUTF8(const FileName: string): THandle; 14begin 15 Result := SysUtils.FileCreate(UTF8ToSys(FileName)); 16end; 17 18function FileCreateUTF8(const FileName: string; Rights: Cardinal): THandle; 19begin 20 Result := SysUtils.FileCreate(UTF8ToSys(FileName), Rights); 21end; 22 23function FileCreateUtf8(const FileName: String; ShareMode: Integer; 24 Rights: Cardinal): THandle; 25begin 26 Result := SysUtils.FileCreate(UTF8ToSys(FileName), ShareMode, Rights); 27end; 28 29function FileGetAttrUTF8(const FileName: String): Longint; 30begin 31 Result:=SysUtils.FileGetAttr(UTF8ToSys(Filename)); 32end; 33 34function FileSetAttrUTF8(const Filename: String; Attr: longint): Longint; 35begin 36 Result:=SysUtils.FileSetAttr(UTF8ToSys(Filename),Attr); 37 InvalidateFileStateCache(Filename); 38end; 39 40function FileExistsUTF8(const Filename: string): boolean; 41begin 42 Result:=SysUtils.FileExists(UTF8ToSys(Filename)); 43end; 44 45function DirectoryExistsUTF8(const Directory: string): Boolean; 46begin 47 Result:=SysUtils.DirectoryExists(UTF8ToSys(Directory)); 48end; 49 50function FileAgeUTF8(const FileName: string): Longint; 51begin 52 Result:=SysUtils.FileAge(UTF8ToSys(Filename)); 53end; 54 55function FileSetDateUTF8(const FileName: String; Age: Longint): Longint; 56begin 57 Result := SysUtils.FileSetDate(UTF8ToSys(Filename), Age); 58 InvalidateFileStateCache(Filename); 59end; 60 61function FileSizeUtf8(const Filename: string): int64; 62var 63 st: baseunix.stat; 64 SysFileName: String; 65begin 66 SysFileName := Utf8ToSys(FileName); 67 if not fpstat(pointer(SysFileName),st{%H-})>=0 then 68 exit(-1); 69 Result := st.st_size; 70end; 71 72{------------------------------------------------------------------------------ 73 function ReadAllLinks(const Filename: string; 74 ExceptionOnError: boolean): string; 75 ------------------------------------------------------------------------------} 76function ReadAllLinks(const Filename: string; 77 ExceptionOnError: boolean): string; 78var 79 LinkFilename: string; 80 AText: string; 81 Depth: Integer; 82begin 83 Result:=Filename; 84 Depth:=0; 85 while Depth<12 do begin 86 inc(Depth); 87 LinkFilename:=FpReadLink(Result); 88 if LinkFilename='' then begin 89 AText:='"'+Filename+'"'; 90 case fpGetErrno() of 91 ESysEAcces: 92 AText:='read access denied for '+AText; 93 ESysENoEnt: 94 AText:='a directory component in '+AText 95 +' does not exist or is a dangling symlink'; 96 ESysENotDir: 97 AText:='a directory component in '+AText+' is not a directory'; 98 ESysENoMem: 99 AText:='insufficient memory'; 100 ESysELoop: 101 AText:=AText+' has a circular symbolic link'; 102 else 103 // not a symbolic link, just a regular file 104 exit; 105 end; 106 if (not ExceptionOnError) then begin 107 Result:=''; 108 exit; 109 end; 110 raise EFOpenError.Create(AText); 111 end else begin 112 if not FilenameIsAbsolute(LinkFilename) then 113 Result:=ResolveDots(ExtractFilePath(Result)+LinkFilename) 114 else 115 Result:=LinkFilename; 116 end; 117 end; 118 // probably an endless loop 119 if ExceptionOnError then 120 raise EFOpenError.Create('too many links, maybe an endless loop.') 121 else 122 Result:=''; 123end; 124 125function GetPhysicalFilename(const Filename: string; 126 OnError: TPhysicalFilenameOnError): string; 127begin 128 Result:=GetUnixPhysicalFilename(Filename,OnError=pfeException); 129 if (Result='') and (OnError=pfeOriginal) then 130 Result:=Filename; 131end; 132 133function GetUnixPhysicalFilename(const Filename: string; 134 ExceptionOnError: boolean): string; 135var 136 OldPath: String; 137 NewPath: String; 138 p: PChar; 139begin 140 Result:=Filename; 141 p:=PChar(Result); 142 repeat 143 while p^='/' do 144 inc(p); 145 if p^=#0 then exit; 146 if p^<>'/' then 147 begin 148 repeat 149 inc(p); 150 until p^ in [#0,'/']; 151 OldPath:=LeftStr(Result,p-PChar(Result)); 152 NewPath:=ReadAllLinks(OldPath,ExceptionOnError); 153 if NewPath='' then exit(''); 154 if OldPath<>NewPath then 155 begin 156 Result:=NewPath+copy(Result,length(OldPath)+1,length(Result)); 157 p:=PChar(Result)+length(NewPath); 158 end; 159 end; 160 until false; 161 Result:=ResolveDots(Result); 162end; 163 164function CreateDirUTF8(const NewDir: String): Boolean; 165begin 166 Result:=SysUtils.CreateDir(UTF8ToSys(NewDir)); 167end; 168 169function RemoveDirUTF8(const Dir: String): Boolean; 170begin 171 Result:=SysUtils.RemoveDir(UTF8ToSys(Dir)); 172end; 173 174function DeleteFileUTF8(const FileName: String): Boolean; 175begin 176 Result:=SysUtils.DeleteFile(UTF8ToSys(Filename)); 177 if Result then 178 InvalidateFileStateCache; 179end; 180 181function RenameFileUTF8(const OldName, NewName: String): Boolean; 182begin 183 Result:=SysUtils.RenameFile(UTF8ToSys(OldName),UTF8ToSys(NewName)); 184 if Result then 185 InvalidateFileStateCache; 186end; 187 188function SetCurrentDirUTF8(const NewDir: String): Boolean; 189begin 190 Result:=SysUtils.SetCurrentDir(UTF8ToSys(NewDir)); 191end; 192 193function FindFirstUTF8(const Path: string; Attr: Longint; out Rslt: TSearchRec 194 ): Longint; 195begin 196 Result:=SysUtils.FindFirst(UTF8ToSys(Path),Attr,Rslt); 197 Rslt.Name:=SysToUTF8(Rslt.Name); 198end; 199 200function FindNextUTF8(var Rslt: TSearchRec): Longint; 201begin 202 Rslt.Name:=UTF8ToSys(Rslt.Name); 203 Result:=SysUtils.FindNext(Rslt); 204 Rslt.Name:=SysToUTF8(Rslt.Name); 205end; 206 207 208function ExpandFileNameUTF8(const FileName: string; BaseDir: string): string; 209var 210 IsAbs: Boolean; 211 CurDir, HomeDir, Fn: String; 212begin 213 Fn := FileName; 214 ForcePathDelims(Fn); 215 IsAbs := FileNameIsUnixAbsolute(Fn); 216 if (not IsAbs) then 217 begin 218 CurDir := GetCurrentDirUtf8; 219 if ((Length(Fn) > 1) and (Fn[1] = '~') and (Fn[2] = '/')) or (Fn = '~') then 220 begin 221 HomeDir := GetEnvironmentVariableUTF8('HOME'); 222 if not FileNameIsUnixAbsolute(HomeDir) then 223 HomeDir := ExpandFileNameUtf8(HomeDir,''); 224 Fn := HomeDir + Copy(Fn,2,length(Fn)); 225 IsAbs := True; 226 end; 227 end; 228 if IsAbs then 229 begin 230 Result := ResolveDots(Fn); 231 end 232 else 233 begin 234 if (BaseDir = '') then 235 Fn := IncludeTrailingPathDelimiter(CurDir) + Fn 236 else 237 Fn := IncludeTrailingPathDelimiter(BaseDir) + Fn; 238 Fn := ResolveDots(Fn); 239 //if BaseDir is not absolute then this needs to be expanded as well 240 if not FileNameIsUnixAbsolute(Fn) then 241 Fn := ExpandFileNameUtf8(Fn, ''); 242 Result := Fn; 243 end; 244end; 245 246function GetCurrentDirUTF8: String; 247begin 248 Result:=SysToUTF8(SysUtils.GetCurrentDir); 249end; 250 251function FileIsExecutable(const AFilename: string): boolean; 252var 253 Info : Stat; 254begin 255 // first check AFilename is not a directory and then check if executable 256 Result:= (FpStat(AFilename,info{%H-})<>-1) and FPS_ISREG(info.st_mode) and 257 (BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)=0); 258end; 259 260procedure CheckIfFileIsExecutable(const AFilename: string); 261var 262 AText: String; 263begin 264 // TProcess does not report, if a program can not be executed 265 // to get good error messages consider the OS 266 if not FileExistsUTF8(AFilename) then begin 267 raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename])); 268 end; 269 if DirPathExists(AFilename) then begin 270 raise Exception.Create(Format(lrsFileIsADirectoryAndNotAnExecutable, [ 271 AFilename])); 272 end; 273 if BaseUnix.FpAccess(AFilename,BaseUnix.X_OK)<>0 then 274 begin 275 AText:='"'+AFilename+'"'; 276 case fpGetErrno() of 277 ESysEAcces: 278 AText:=Format(lrsReadAccessDeniedFor, [AText]); 279 ESysENoEnt: 280 AText:=Format(lrsADirectoryComponentInDoesNotExistOrIsADanglingSyml, [ 281 AText]); 282 ESysENotDir: 283 AText:=Format(lrsADirectoryComponentInIsNotADirectory, [Atext]); 284 ESysENoMem: 285 AText:=lrsInsufficientMemory; 286 ESysELoop: 287 AText:=Format(lrsHasACircularSymbolicLink, [AText]); 288 else 289 AText:=Format(lrsIsNotExecutable, [AText]); 290 end; 291 raise Exception.Create(AText); 292 end; 293 // ToDo: xxxbsd 294end; 295 296function FileIsSymlink(const AFilename: string): boolean; 297begin 298 Result := FpReadLink(AFilename) <> ''; 299end; 300 301procedure CheckIfFileIsSymlink(const AFilename: string); 302var 303 AText: string; 304begin 305 // to get good error messages consider the OS 306 if not FileExistsUTF8(AFilename) then begin 307 raise Exception.Create(Format(lrsFileDoesNotExist, [AFilename])); 308 end; 309 if FpReadLink(AFilename)='' then begin 310 AText:='"'+AFilename+'"'; 311 case fpGetErrno() of 312 ESysEAcces: 313 AText:=Format(lrsReadAccessDeniedFor, [AText]); 314 ESysENoEnt: 315 AText:=Format(lrsADirectoryComponentInDoesNotExistOrIsADanglingSyml2, [ 316 AText]); 317 ESysENotDir: 318 AText:=Format(lrsADirectoryComponentInIsNotADirectory2, [Atext]); 319 ESysENoMem: 320 AText:=lrsInsufficientMemory; 321 ESysELoop: 322 AText:=Format(lrsHasACircularSymbolicLink, [AText]); 323 else 324 AText:=Format(lrsIsNotASymbolicLink, [AText]); 325 end; 326 raise Exception.Create(AText); 327 end; 328end; 329 330function FileIsHardLink(const AFilename: string): boolean; 331var 332 H: THandle; 333 FileInfo: stat; 334begin 335 Result := false; 336 H := FileOpenUtf8(aFilename, fmOpenRead); 337 if H <> feInvalidHandle then 338 begin 339 if FPFStat(H, FileInfo{%H-}) = 0 then 340 Result := (FileInfo.st_nlink > 1); 341 FileClose(H); 342 end; 343end; 344 345function FileIsReadable(const AFilename: string): boolean; 346begin 347 Result := BaseUnix.FpAccess(AFilename, BaseUnix.R_OK) = 0; 348end; 349 350function FileIsWritable(const AFilename: string): boolean; 351begin 352 Result := BaseUnix.FpAccess(AFilename, BaseUnix.W_OK) = 0; 353end; 354 355 356function IsUNCPath(const Path: String): Boolean; 357begin 358 Result := false; 359end; 360 361function ExtractUNCVolume(const Path: String): String; 362begin 363 Result := ''; 364end; 365 366function GetFileDescription(const AFilename: string): string; 367var 368 info: Stat; 369 // permissions 370 // user 371 // group 372 // size 373 // date 374 // time 375 mode: mode_t; 376begin 377 Result:=''; 378 if not (FpStat(AFilename,info{%H-})=0) then exit; 379 380 // permissions 381 // file type 382 mode:= info.st_mode; 383 if STAT_IFLNK and mode=STAT_IFLNK then 384 Result:=Result+'l' 385 else 386 if STAT_IFDIR and mode=STAT_IFDIR then 387 Result:=Result+'d' 388 else 389 if STAT_IFBLK and mode=STAT_IFBLK then 390 Result:=Result+'b' 391 else 392 if STAT_IFCHR and mode=STAT_IFCHR then 393 Result:=Result+'c' 394 else 395 Result:=Result+'-'; 396 // user permissions 397 if STAT_IRUSR and mode=STAT_IRUsr then 398 Result:=Result+'r' 399 else 400 Result:=Result+'-'; 401 if STAT_IWUsr and mode=STAT_IWUsr then 402 Result:=Result+'w' 403 else 404 Result:=Result+'-'; 405 if STAT_IXUsr and mode=STAT_IXUsr then 406 Result:=Result+'x' 407 else 408 Result:=Result+'-'; 409 // group permissions 410 if STAT_IRGRP and mode=STAT_IRGRP then 411 Result:=Result+'r' 412 else 413 Result:=Result+'-'; 414 if STAT_IWGRP and mode=STAT_IWGRP then 415 Result:=Result+'w' 416 else 417 Result:=Result+'-'; 418 if STAT_IXGRP and mode=STAT_IXGRP then 419 Result:=Result+'x' 420 else 421 Result:=Result+'-'; 422 // other permissions 423 if STAT_IROTH and mode=STAT_IROTH then 424 Result:=Result+'r' 425 else 426 Result:=Result+'-'; 427 if STAT_IWOTH and mode=STAT_IWOTH then 428 Result:=Result+'w' 429 else 430 Result:=Result+'-'; 431 if STAT_IXOTH and mode=STAT_IXOTH then 432 Result:=Result+'x' 433 else 434 Result:=Result+'-'; 435 436 437 // user name 438 //Result:=Result+' Owner: '+IntToStr(info.uid)+'.'+IntToStr(info.gid); 439 440 // size 441 Result:=Result+lrsSize+IntToStr(info.st_size); 442 443 // date + time 444 Result:=Result+lrsModified; 445 try 446 Result:=Result+FormatDateTime('DD/MM/YYYY hh:mm', 447 FileDateToDateTime(FileAgeUTF8(AFilename))); 448 except 449 Result:=Result+'?'; 450 end; 451end; 452 453 454function GetAppConfigDirUTF8(Global: Boolean; Create: boolean = false): string; 455begin 456 Result := SysToUTF8(SysUtils.GetAppConfigDir(Global)); 457 if Result = '' then exit; 458 if Create and not ForceDirectoriesUTF8(Result) then 459 raise EInOutError.Create(Format(lrsUnableToCreateConfigDirectoryS,[Result])); 460end; 461 462function GetAppConfigFileUTF8(Global: Boolean; SubDir: boolean; 463 CreateDir: boolean): string; 464var 465 Dir: string; 466begin 467 Result := SysToUTF8(SysUtils.GetAppConfigFile(Global,SubDir)); 468 if not CreateDir then exit; 469 Dir := ExtractFilePath(Result); 470 if Dir = '' then exit; 471 if not ForceDirectoriesUTF8(Dir) then 472 raise EInOutError.Create(Format(lrsUnableToCreateConfigDirectoryS,[Dir])); 473end; 474 475function GetShellLinkTarget(const FileName: string): string; 476begin 477 Result := Filename; 478end; 479 480procedure InitLazFileUtils; 481begin 482 //dummy 483end; 484 485procedure FinalizeLazFileUtils; 486begin 487 //dummy 488end; 489