os.Stat() returns a FileInfo object, which has a Sys() method that returns an Interface{} with no methods.
Though I am able to fmt.Printf() it to "see" the "Gid", I am unable to access "Gid" programmatically.
How do I retrieve the "Gid" of a file here?
file_info, _ := os.Stat(abspath)
file_sys := file_info.Sys()
fmt.Printf("File Sys() is: %+v", file_sys)
Prints:
File Sys() is: &{Dev:31 Ino:5031364 Nlink:1 Mode:33060 Uid:1616 Gid:31 X__pad0:0 Rdev:0 Size:32 Blksize:32768 Blocks:0 Atim:{Sec:1564005258 Nsec:862700000} Mtim:{Sec:1563993023 Nsec:892256000} Ctim:{Sec:1563993023 Nsec:893251000} X__unused:[0 0 0]}
Note: I do not need a portable solution, it just has to work on Linux (notable because Sys() is known to be flaky).
Possibly related: Convert interface{} to map in Golang
The reflect module showed that the data type for Sys()'s return is *syscall.Stat_t, so this seems to work to get the Gid of a file as a string:
file_info, _ := os.Stat(abspath)
file_sys := file_info.Sys()
file_gid := fmt.Sprint(file_sys.(*syscall.Stat_t).Gid)
Please let me know if there is a better way to do this.
Related
Id like to uncompress a file with bzip2 myFile.bz2 which class do I have to use for that?
I tried to find it into base kernel documentation which made the most sense for me and didn't find it
This works:
make
local
l_env:EXECUTION_ENVIRONMENT
do
create l_env
l_env.system ("bzip2 test.txt")
end
My final solution working on linux with pipes is following:
feature -- Commands
piped_command_result (a_command: STRING): detachable PROCESS_COMMAND_RESULT
-- https://groups.google.com/forum/#!topic/eiffel-users/O9KEtBSPrf4
local
l_cmd: READABLE_STRING_32
l_args: ARRAYED_LIST [READABLE_STRING_32]
l_proc: like {BASE_PROCESS_FACTORY}.process_launcher
l_err, l_res: STRING
l_err_spec, l_res_spec: SPECIAL [NATURAL_8]
do
create l_res.make (0)
create l_err.make (0)
create l_res_spec.make_filled (0, 1024)
create l_err_spec.make_filled (0, 1024)
l_cmd := (create {EXECUTION_ENVIRONMENT}).default_shell
if l_cmd.is_empty then
l_cmd := {STRING_32} "/bin/bash" -- or either "/bin/sh"
end
create l_args.make (2)
l_args.extend ("-c")
l_args.extend (a_command)
l_proc := (create {BASE_PROCESS_FACTORY}).process_launcher (l_cmd, l_args, Void)
l_proc.set_hidden (True)
l_proc.set_separate_console (False)
l_proc.redirect_output_to_stream
l_proc.redirect_error_to_stream
l_proc.launch
check
process_launched: l_proc.launched
then
-- read output
from
until
l_proc.has_output_stream_closed or l_proc.has_output_stream_error
loop
l_proc.read_output_to_special (l_res_spec)
append_special_of_natural_8_to_string_8 (l_res_spec, l_res)
end
-- read error
from
until
l_proc.has_error_stream_closed or l_proc.has_error_stream_error
loop
l_proc.read_error_to_special (l_err_spec)
append_special_of_natural_8_to_string_8 (l_err_spec, l_err)
end
l_proc.wait_for_exit
create Result.make (l_proc.exit_code, l_res, l_err)
end
ensure
instance_free: Class
end
feature {NONE} -- Implementation
append_special_of_natural_8_to_string_8 (spec: SPECIAL [NATURAL_8]; a_output: STRING)
local
i,n: INTEGER
do
from
i := spec.lower
n := spec.upper
until
i > n
loop
a_output.append_code (spec[i])
i := i + 1
end
ensure
instance_free: Class
end
Credits to google groups eiffel users
Note that with another user like an app launched by apache, you have to check your environment variables and $PATH so that it can work!
I have an unknown identifier on the local like some_values.cursor, I really don't understand why!
qry_update_set_fields (some_keys, some_values, some_unstored_field_names: LINKED_LIST[STRING]): STRING
require
same_some_keys_some_values_count: some_keys.count = some_values.count
local
l_val_c: like some_values.new_cursor
do
Result := ""
l_val_c := some_values.new_cursor
across
some_keys as l_key_c
loop
Result := l_key_c.item + "=" + l_val_c.item + ","
l_val_c.forth
end
if Result.ends_with (",") then
Result.remove_tail (1)
end
ensure
dont_modify_parameters: old some_keys.is_equal (some_keys) and old some_values.is_equal (some_values)
end
working
l_val_c: LINKED_LIST_CURSOR [STRING]
Neither working
l_val_c: LINKED_LIST_CURSOR [like some_values.item]
The example tries using an argument in the qualified anchored type like argument.some_feature. This is not supported. Types, anchored to arguments, are not part of the standard Eiffel and are supported only for backward compatibility in the form like argument.
I am contemplating the migration from Advantage Native Delphi components to FireDAC. I have been searching for a way to determine how with FireDAC I can determine the method that was used to connect to the server - Remote, Local, AIS (Internet).
I would be looking for the equivalent of TAdsConnection.ConnectionType.
Thanks
Gary Conley
The function you're looking for is called AdsGetConnectionType. Its import you can find declared in the FireDAC.Phys.ADSCli module, but it's not used anywhere.
But it's not so difficult to get its address and call it by yourself. For example (not a good one):
uses
FireDAC.Stan.Consts, FireDAC.Phys.ADSCli, FireDAC.Phys.ADSWrapper;
var
FTAdsGetConnectionType: TAdsGetConnectionType = nil;
type
TADSLib = class(FireDAC.Phys.ADSWrapper.TADSLib)
end;
function GetConnectionType(Connection: TFDConnection): Word;
const
AdsGetConnectionTypeName = 'AdsGetConnectionType';
var
CliLib: TADSLib;
CliCon: TADSConnection;
Status: UNSIGNED32;
Output: UNSIGNED16;
begin
Result := 0;
CliCon := TADSConnection(Connection.CliObj);
CliLib := TADSLib(CliCon.Lib);
if not Assigned(FTAdsGetConnectionType) then
FTAdsGetConnectionType := CliLib.GetProc(AdsGetConnectionTypeName);
if Assigned(FTAdsGetConnectionType) then
begin
Status := FTAdsGetConnectionType(CliCon.Handle, #Output);
if Status = AE_SUCCESS then
Result := Word(Output)
else
FDException(CliLib.OwningObj, EADSNativeException.Create(Status, CliLib, nil),
{$IFDEF FireDAC_Monitor}True{$ELSE}False{$ENDIF});
end
else
FDException(CliLib.OwningObj, [S_FD_LPhys, CliLib.DriverID],
er_FD_AccCantGetLibraryEntry, [AdsGetConnectionTypeName]);
end;
Possible usage:
case GetConnectionType(FDConnection1) of
ADS_AIS_SERVER: ShowMessage('AIS server');
ADS_LOCAL_SERVER: ShowMessage('Local server');
ADS_REMOTE_SERVER: ShowMessage('Remove server');
end;
I am uploading a file via the following code.
After a successful upload I am attempting to Delete the file but I am getting a 32 - File in use error.
Can anyone tell me how I can resolve this file in use error? The following code is uploading the file, but not releasing it when done..
var
HTTP: TidHTTP;
SSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
PostData: TIdMultiPartFormDataStream;
ResponseStream: TStringStream;
Delete : Boolean;
begin
ResponseStream := TStringStream.Create('');
HTTP := TidHTTP.Create(nil);
SSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
SSLIOHandler.SSLOptions.Method := sslvSSLv3;
HTTP.ReadTimeout := 30000; //30 seconds
HTTP.ConnectTimeout := 30000; //30 seconds
HTTP.IOHandler := SSLIOHandler;
HTTP.HTTPOptions := [hoKeepOrigProtocol];
HTTP.ProtocolVersion := pv1_1;
PostData := TIdMultiPartFormDataStream.Create;
PostData.AddFormField('username', 'demo');
PostData.AddFormField('password', 'demo');
PostData.AddFormField('action', 'upload');
PostData.AddFormField('accountno', 'demo');
PostData.AddFile('uploadedfile', FileName, GetMIMETypeFromFile(FileName));
HTTP.Request.ContentType := PostData.RequestContentType;
HTTP.Post('http://uploadsite.com/ex/exampleAPI.asmx/Process', PostData, ResponseStream);
if AnsiContainsStr(ResponseStream.DataString, 'Done') then
Delete := True;
finally
SSLIOHandler.Free;
HTTP.Free;
ResponseStream.Free;
end;
if Delete then
if DeleteFile(BFlashFileName) then
ShowMessage('Deleted')
else ShowMessage(BFlashFileName+' not deleted, error = '+
IntToStr(GetLastError));
Call the Clear method of your TIdMultiPartFormDataStream instance before attempting to delete the file. If you don't need it anymore, freeing it will also amount to same (i.e. PostData.Free). Currently, it looks like you're leaking your PostData variable.
While TIdMultiPartFormDataStream is clearing its Fields collection, the file stream created by the AddFile method will be destroyed closing the file's handle.
I've been searching now for HOURS on Google (and here).
And I cannot find a solution.
I want to CHANGE the "Created Filetime" (= creation filetime) in DELPHI 6.
Not the "Modified file time" (for which a simple call to "FileSetDate()" is needed)
and not the "Last accessed file time".
How do I do this?
Call the SetFileTime Windows API function. Pass nil for lpLastAccessTime and lpLastWriteTime if you only want to modify the creation time.
You will need to obtain a file handle by calling CreateFile, or one of the Delphi wrappers, so this is not the most convenient API to use.
Make life easier for yourself by wrapping the API call up in a helper function that receives the file name and a TDateTime. This function should manage the low-level details of obtaining and closing a file handle, and converting the TDateTime to a FILETIME.
I would do it like this:
const
FILE_WRITE_ATTRIBUTES = $0100;
procedure SetFileCreationTime(const FileName: string; const DateTime: TDateTime);
var
Handle: THandle;
SystemTime: TSystemTime;
FileTime: TFileTime;
begin
Handle := CreateFile(PChar(FileName), FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, 0);
if Handle=INVALID_HANDLE_VALUE then
RaiseLastOSError;
try
DateTimeToSystemTime(DateTime, SystemTime);
if not SystemTimeToFileTime(SystemTime, FileTime) then
RaiseLastOSError;
if not SetFileTime(Handle, #FileTime, nil, nil) then
RaiseLastOSError;
finally
CloseHandle(Handle);
end;
end;
I had to add the declaration of FILE_WRITE_ATTRIBUTES because it is not present in the Delphi 6 Windows unit.
Based on FileSetDate, you can write a similar routine:
function FileSetCreatedDate(Handle: Integer; Age: Integer): Integer;
var
LocalFileTime, FileTime: TFileTime;
begin
Result := 0;
if DosDateTimeToFileTime(LongRec(Age).Hi, LongRec(Age).Lo, LocalFileTime) and
LocalFileTimeToFileTime(LocalFileTime, FileTime) and
SetFileTime(Handle, #FileTime, nil, nil) then Exit;
Result := GetLastError;
end;