How can I get last modified timestamp in Lua - file

I am trying to work on Lua file handling.
So, I am able to open, read, write, close the files.
local session_debug = io.open("/root/session_debug.txt", "a")
session_debug:write("Some text\n")
session_debug:close()
How can I know the last modified date timestamp of this file.

There's no built-in function in standard Lua that does this. One way to get it without third-party libraries is to take use of io.popen.
For example, on Linux, you could use stat:
local f = io.popen("stat -c %Y testfile")
local last_modified = f:read()
Now last_modified is the timestamp of the last modified time of testfile. On my system,
print(os.date("%c", last_modified))
Outputs Sat Mar 22 08:36:50 2014.

If you don't mind using a library, LuaFileSystem allows you to get the modified timestamp as follows:
local t = lfs.attributes(path, 'modification')
A more elaborate example with error handling (will print the name and date of modification of the first argument passed to the script):
local lfs = require('lfs')
local time, err = lfs.attributes(arg[1], 'modification')
if err then
print(err)
else
print(arg[1], os.date("%c", time))
end

Related

Dart - How can I get the creationTime of a File?

I need to get the creationTime of a File in my Flutter project but all I have from a File object is lastModified() and lastAccessed(), no trace of a method to get the DateTime of creation.
I see that in Java it is possible: https://stackoverflow.com/a/2724009/3997782
and also in Swift: https://stackoverflow.com/a/6428757/3997782
I could use the Flutter MethodChannel function to get that but I would like to know if there a native Dart way to get it.
How to get the local file information, such as file creation time
Not all platforms does have a concept of file creation time. E.g. Linux does not for all file systems and the general stat() call does not provide that information.
That does not mean you cannot access what seems to be creation time. But you should not necessarily trust its value which are also documented in the Java API:
Returns the creation time. The creation time is the time that the file was created.
If the file system implementation does not support a time stamp to indicate the time when the file was created then this method returns an implementation specific default value, typically the last-modified-time or a FileTime representing the epoch (1970-01-01T00:00:00Z).
https://docs.oracle.com/javase/7/docs/api/java/nio/file/attribute/BasicFileAttributes.html#creationTime()
Dart does have a similar API if you use the FileStat class which have this property:
DateTime changed
The time of the last change to the data or metadata of the file system object.
On Windows platforms, this is instead the file creation time.
https://api.dart.dev/stable/2.7.2/dart-io/FileStat/changed.html
But the data for FileStat is documented to come from the POSIX stat() system call which does not have a concept of creation timestamp of files but has the following:
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
Which maps to the three timestamps you can get from FileStat:
import "dart:io";
main() {
final stat = FileStat.statSync("test.dart");
print('Accessed: ${stat.accessed}');
print('Modified: ${stat.modified}');
print('Changed: ${stat.changed}');
}
But as you can see on Linux with XFS it will return the same value for changed and modified:
[julemand101#beta ~]$ dart test.dart
Accessed: 2020-04-07 18:19:20.404
Modified: 2020-04-07 18:19:19.020
Changed: 2020-04-07 18:19:19.020
You can get a different changed time if you e.g. update inode information:
[julemand101#beta ~]$ chmod +x test.dart
[julemand101#beta ~]$ dart test.dart
Accessed: 2020-04-07 18:19:42.341
Modified: 2020-04-07 18:19:19.020
Changed: 2020-04-07 18:19:39.397
Which makes sense since the st_ctime is documented as:
The field st_ctime is changed by writing or by setting inode information (i.e., owner, group, link count, mode, etc.).
https://linux.die.net/man/2/stat
So in short, you should try and see what happens for iOS and Android when using FileStat. But in short, it is difficult to write a platform independent API which gives access to differences at each platform. Especially for a platform like Linux where it is up to each file system if a feature exists or not.

DBF File with unreadable fields. Are they encrypted, encoded weird, or something else?

I have a program that installs an updated database monthly into a special software we use. I get an .exe, run it, the .exe "installs" a bunch of DBF/CDX files into a folder, and then "hooks up" the database info into our software somehow.
Here is what the "installation" output folder looks like every month:
I've opened the DBF I'm most interested pulling info from (parts.dbf) (with at least 4 different pieces of software I believe) and browsed the data. Most of the fields look fine, readable, all is good. However, the 2 fields that I NEED (Prices and Part Numbers) are unreadable. In the Parts column all of the fields show 10 or 12 characters followed by a bunch of 9's (examples:<\MFMIFJHMFll999999999999999999, KI9e^Z]pbk^999999999999999999, JIFIPKMFL999999999999999999999). In the Price column its similar, just not as many characters (examples: LJKLGIQ999, IGII999999, JMQJGLL999).
Here is a screenshot of what I'm seeing exactly:
I have googled just about everything I know to google. I've downloaded different programs, tried to pull the data into Crystal Reports, tried to encode it differently (not sure I did that right, though), tried to figure out how to decrypt it (that journey was short-lived because it was so over my head), and just generally been pulling my hair out over this for weeks. I don't know what to do because I don't even really know where to begin. I'm just stabbing in the dark.
I THINK this file was created in some version of FoxPro but I could be wrong. When I view the information in our software it all shows up fine. Part Numbers and Prices look like readable human characters.
Example of data in our software:
I'm out of ideas. I need to know what I'm working with so I can work on figuring out how to "fix it". Is this a FoxPro file? Is it encoded in a way that I need to change? Is it encrypted data in those two fields? Am I way off on everything?
Ideally, I'd love to pull this data into Crystal Reports and do my reporting thing with the data. Even Excel could probably work okay. As it stands though I can't do much reporting with a bunch of weird characters and 9's.
Any help with this would be greatly appreciated.
Screenshot of Schema, per comment section:
Yes, 0x03 in header's first byte it is a Foxbase table. As cHao already pointed out, the author decided to create those columns with some byte shifting of each character (I wouldn't call that encryption though, too easy to solve for any programmer - or non-programmer with some pattern discovery).
Now the question is how you can utilize that data without damaging the original. One idea is to take a copy, alter the data in it and use that copy instead. Doing that with some computer language is easy when you are a programmer, but you are saying you are not. Then comes the question, which language code you could simply get and compile on your computer.
Well I wanted to play with this as a skill testing for myself and came up with some C# code. It was quite easy to write, and compile on any windows machine (so I thought, I had been doing that since years ago). I was mistaken, I don't know why nor have a will to investigate, but the executable created using command line compiler (any windows have it already) is blocked by my antivirus! I signed it but nothing changed. I gave up very quickly.
Luckily there was another choice which I think is better anyways. Go < g > write and compile with Go - the fantastic language from Google. If you want to spare your 10-15 mins at most to it, I will give you the code and how to compile it into an exe on your computer. First here is the code itself:
package main
import (
"fmt"
"log"
"path/filepath"
"strings"
"os"
"io"
"time"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-adodb"
)
func main() {
if len(os.Args) != 2 {
log.Fatal("You need to supply an input filename.")
}
source := os.Args[1]
if _, err := os.Stat(source); os.IsNotExist(err) {
log.Fatal(fmt.Sprintf("File [%s] doesn't exist.", source))
}
log.Println(fmt.Sprintf("Converting [%s]...", source))
saveAs := GetSaveAsName(source)
log.Println(fmt.Sprintf("Started conversion on copy [%s]", saveAs))
ConvertData(saveAs)
log.Println("Conversion complete.")
}
func ConvertData(filename string) {
srcBytes := make([]byte, 127-32-1)
dstBytes := make([]byte, 127-32-1)
for i := 32; i < 34;i++ {
srcBytes[i-32]=byte(i+25)
dstBytes[i-32]=byte(i)
}
for i := 35; i < 127; i++ {
srcBytes[i-33] = byte(i+25)
dstBytes[i-33] = byte(i)
}
src := string(srcBytes) + string(byte('"')+25)
dst := string(dstBytes)
dbPath, dbName := filepath.Split(filename)
db, err := sqlx.Open("adodb", `Provider=VFPOLEDB;Data Source=` + dbPath)
e(err)
defer db.Close()
stmt := fmt.Sprintf(`update ('%s') set
p_part_num = chrtran(p_part_num, "%s", "%s"+'"'),
p_price = chrtran(p_price, "%s", "%s"+'"')`,
dbName, src, dst, src, dst)
_, err = db.Exec(stmt)
e(err)
}
func GetSaveAsName(source string) string {
fp, err := filepath.Abs(source)
e(err)
dir, fn := filepath.Split(fp)
targetFileName := filepath.Join(dir,
fmt.Sprintf("%s_copy%d.dbf",
strings.Replace(strings.ToLower(fn), ".dbf", "", 1),
time.Now().Unix()))
e(err)
in, err := os.Open(source)
e(err)
defer in.Close()
out, err := os.Create(targetFileName)
e(err)
defer out.Close()
_, err = io.Copy(out, in)
e(err)
err = out.Close()
e(err)
return targetFileName
}
func e(err error) {
if err != nil {
log.Fatal(err)
}
}
And here are the steps to create an executable out of it (and have Go as a language on your computer for other needs:)
Download Go language from Google and install it. Its installer is simple to use and finish in a few seconds.
Open a command prompt. Type:
Go version [enter]
-You should see installed Go's version (as of now 1.10).
-Type
Go env [enter]
and check GOPATH , it points the base folder for your go projects. Go to that folder and create 4 folders named:
bin, pkg, src and vendor
By default GOPATH is "Go" under your home folder, looks like this:
c:\users\myUserName\Go
after creating folders you would have:
c:\users\myUserName\Go
c:\users\myUserName\Go\bin
c:\users\myUserName\Go\pkg
c:\users\myUserName\Go\src
c:\users\myUserName\Go\vendor
using any text editor (Notepad.exe for example) copy & paste and save the code as say "MyCustomConverter.go" into src folder.
Code has 2 external libraries that you need to get. Change directory to your GOPATH (not really necessary but my habit at least) and get those libraries typing:
cd %GOPATH%
go get -v github.com/jmoiron/sqlx
go get -v github.com/mattn/go-adodb
You are ready to compile your code.
cd src
set GOARCH=386
go build MyCustomConverter.go
This would create MyCustomConverter.exe that you can use for conversion.
set GOARCH=386 is needed in this special case, because VFP OLEDB driver is 32 bits driver.
Oh I forgot to tell, it uses VFPOLEDB driver, which you can download from here and install.
You would use the executable like this:
MyCustomConverter.exe "c:\My Folder\parts.dbf"
and it would create a modified version of that named as:
"c:\My Folder\parts_copyXXXXXXXXXX.dbf"
where XXXXXXXXXXX would be a timestamp value (so whenever you run you create another copy, it doesn't overwrite on to one that may exist).
Instead of going to command prompt everytime and typing the fullpath of your parts table, you could copy the MyCustomConverter.exe file on to desktop and drag & drop your parts.dbf on to that exe from windows explorer.
(It was a nice exercise for my Go coding - there would be critics such as why I didn't use parameters but I really had good reasons, driver and the Go library support namely:)
I THINK this file was created in some version of FoxPro
While the DBF Data Tables were CREATED by Foxpro, they are POPULATED by an APPLICATION which may or may not have been written in Foxpro.
And yes, you do not need to worry about the CDX files unless you want to organize (sequence) the data by one of its Indexes or to establish Relationships between multiple Data Tables for processing purposes. However unless you were to do that using Foxpro/Visual Foxpro itself, it wouldn't be of use to you anyway.
From the comments that you have already received, it looks as though the developers of the APPLICATION that writes the field values into the DBF Data Tables might have encrypted the data. And it also seems like you may have found how to decrypt it using the suggestions above.
I'm no programmer unfortunately
If that is the case then I'd suggest that you STOP RIGHT NOW before you introduce more problems than you want. Blindly 'mucking' around with the data might just make things worse.
If this project is BUSINESS CRITICAL then you should hire a software consultant familiar with Foxpro/Visual Foxpro to get the work done - after which you can do whatever you want. Remember that if something is BUSINESS CRITICAL then it is worth spending the $$$$
Good Luck

How to set the timezone permanently in ubuntu using C program

When i write -
root#XYZ:/home/timez# export TZ=UTC; date
Thu Nov 13 05:35:36 UTC 2014
It change the date & timezone. I want a equivalent C program of this.
I wrote a C program to set Timezone in my Ubuntu machine using code -
system(" export TZ=CST6CDT; date ");
i can see the date in CST as output but this program is not setting Ubuntu Timezone to CST, it is still in UTC.
There exists a settimeofday call inherited from Unix V7 or even before ... that used to set a time zone value in the kernel. But my current man says now : Note: timezone is no longer used; this information is kept outside the kernel.
So in system less than 20 years old, the time zone is only kept in the environment. And the environment has the following property :
a child inherit the environment of its parent but cannot modify its parent's environment
That means that any C program can modify its TZ via a simple setenv call, and this new timezone will be used by itself and all its childs, but it will never be able to modify the environment of the shell that started it. The only possibility would be a special API offered by shell programs, but I know none that implements such a thing.
I know it is a you can't answer but it is the best I can do ...

C script running as cron giving permission denied error

I have a .c file compiled and would like to run via a cron job but I end up getting this error:
/bin/sh: /usr/local/bin/get1Receive.c: Permission denied.
What is causing this error and how do I fix it?
Should I be running the .c file in cron or a different compiled file?
Results from /tmp/myvars
GROUPS=()
HOME=/root
HOSTNAME=capture
HOSTTYPE=x86_64
IFS='
'
LOGNAME=root
MACHTYPE=x86_64-redhat-linux-gnu
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/bin:/bin
POSIXLY_CORRECT=y
PPID=11086
PS4='+ '
PWD=/root
SHELL=/bin/sh
SHELLOPTS=braceexpand:hashall:interactive-comments:posix
SHLVL=1
TERM=dumb
UID=0
USER=root
_=/bin/sh
Results from file get1Receive.c
file get1Receive.c
get1Receive.c: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
Snippet of codes.
sprintf(queryBuf1,"SELECT ipDest, macDest,portDest, sum(totalBits) FROM dataReceive WHERE timeStampID between '%s' And '%s' GROUP BY ipDest, macDest, portDest ",buff1,buff2);
printf("\nQuery receive %s",queryBuf1);
if(mysql_query(localConn, queryBuf1))
{
//fprintf(stderr, "%s\n", mysql_error(localConn));
printf("Error in first query of select %s\n",mysql_error(localConn));
exit(1);
}
localRes1 = mysql_store_result(localConn);
int num_fields = mysql_num_fields(localRes1);
printf("\nNumf of fields : %d",num_fields);
printf("\nNof of row : %lu",mysql_num_rows(localRes1));
If the output of this command:
file get1Receive1.c
shows that file name to be a valid executable that part is very unusual, but okay.
Assuming you are using biz14 (or your real username's ) crontab try this:
use the command crontab -e to create this line in your crontab:
* * * * * set > /tmp/myvars
Wait a few minutes, go back into crontab -e and delete that entry.
Use the set command from the command line to see what variables and aliases exist.
Compare that with that you see in /tmp/myvars You have to change how your C code executes by changing the variables and aliases the cron job runs with.
If you are running the cron job in someone else's crontab, then you have a bigger problem. Check file permissions on get1Receive1.c. and the directory it lives in. That other user (the one who wons the crontab) has to have permissions set on your directory and get1Receive1.c so the job can run.
Example crontab entry:
0 10 * * 1-5 /path/to/get1Receive1.c > /tmp/outputfile
Read /tmp/outputfile to see what you got. You are using printf in your code. printf only writes to the controlling terminal. There is no controlling terminal, so redirect the printf stuff to a file.
Last effort on this problem:
Check return codes on EVERYTHING. All C functions like fread(), any db function, etc. If a return code gives a fail response ( these are different for different function calls) then report the error number the line number and function - gcc provides LINE and func. Example:
printf("error on line %d in my code %s, error message =%s\n", __LINE__, __func__, [string of error message]);
If you do not check return codes you are writing very poor C code.
CHECK return codes, please, now!
Permission wise you could have two issues.
1. The 'c' file's permissions don't allow who you are running it as to run it.
2. You are running the cron with a script which doesn't have permissions.
Here's a helpful post: How to give permission for the cron job file?
The fact that you are running a 'c' file and referring to it as a script makes me think you're using C shell and not writing it as a C language program which would need to be compiled and have the generated executable run by the cron. If you're not using gcc or have never called gcc on your 'C' script then it's not C and call it C shell to avoid confusion.

Find the oldest file within a directory in C on Windows

I am working on a C project and I am trying to find the oldest file within a directory so that that once the oldest file has been found, it is then deleted. I can not find anything on how to do this in C using windows, have found ways to do it in Linux but I need a version for Windows.
Basically you scan the directory, same as in Linux (but you could check out the Boost library also).
The data about time and date are already available in the directory scan structure
HANDLE fh;
FILETIME oldest = {-1U, -1U};
// Buffer to hold file name
oldestFile = malloc(MAX_PATH);
fd = malloc(sizeof(WIN32_FIND_DATA));
if (INVALID_HANDLE_VALUE == (fh = FindFirstFile(directory_name, fd)))
// Signal error, free memory, (and return an error code?)
// OK to proceed
do
{
if(fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
//
if ((fd->ftCreationTime.dwHighDateTime < oldest.dwHighDateTime)
|| (fd->ftCreationTime.dwHighDateTime == oldest.dwHighDateTime
&& fd->ftCreationTime.dwLowDateTime < oldest.dwLowDateTime))
{
oldest.dwHighDateTime = fd->ftCreationTime.dwHighDateTime; // ftLastAccessTime? ftLastWriteTime?
oldest.dwLowDateTime = fd ->ft CreationTime.dwLowDateTime;
strncpy(oldestFile, MAX_PATH, fd->cFileName);
}
} while(FindNextFile(fh, fd));
FindClose(fh);
free(fd); fd = NULL;
You'll want to use the FindFirstFile/FindNextFile combination on Windows to get the files in the directory. You can then either use stat as you would in Linux, or GetFileAttributesEx to check the dates.
Since windows is POSIX compliant, you should be able to read a directory and do a stat() on the files.
You could use the GetFileAttributesEx() function which populates a WIN32_FILE_ATTRIBUTE_DATA struct which has three time related members:
ftCreationTime
ftLastAccessTime
ftLastWriteTime
You can compare whichever of these is more relevant and keep track of the oldest file found during iteration. Once iteration is over, delete it using DeleteFile(). The time members are of type FILETIME and can be compared using CompareFileTime().
Or use the GetFileTime() to obtain the relevant time attribute, as commented by BeyondSora.
For finding the details of file in windows you'll have to refer to File Allocation Table which includes all the details about the files.
Check here for the coding part to read FAT

Resources