Is there is a way to write to txt file from an e (hardware language) code and then to write to the same file from a C code ?
In general, access to files is controlled by the Operating System.
Any number of programs, running on any number of separate processes can access the same file if they use the locking & synchronization methods provided by the Operating System.
This will typically involve opening the file in a Shared or Exclusive mode, opening it for Reading, Writing or both, and setting buffering options. It may also involve sharing a lock-mechanism, such as a mutex, between different programs.
You can have C code like following:
static FILE *f = NULL;
void cwrite() {
if (f == NULL)
f = fopen("ec.txt", "a");
fprintf(f, "print from C\n");
}
And then use it from e together with e write:
routine cwrite();
extend sys {
!f: file;
run() is also {
f = files.open("ec.txt", "a", "Text file");
for i from 0 to 100 {
files.write(f, "print from e");
cwrite();
};
};
};
However, the tricky part is that on linux level, fopen in C and files.open in e create separate file descriptors for exactly the same file, and this can lead to very weird result.
To make it synced, you should either keep your file closed when not writing (which might mean unneeded performance overhead), or really write only from one language, and when you need to write from another - send it as a string to the one that actually does that, you only need to define some simple API for that.
Related
I'm writing a C program and I would like to be able to store data inside the executable file.
I tried making a function to write a single byte at the end of the file but it looks like it can't open the file because it reaches the printf and then gives "segmentation fault".
void writeByte(char c){
FILE *f;
f = fopen("game","wb");
if(f == 0)
printf("\nFile not found\n");
fseek(f,-1,SEEK_END);
fwrite(&c,1,sizeof(char),f);
fclose(f);
}
The file is in the correct directory and the name is correct. When I try to read the last byte instead of writing it works without problems.
Edit: I know I should abort the program instead of trying to write anyway but my main problem is that the program can't open the file despite being in the same directory.
There are several unrelated problems in your code and the problem you're trying to solve.
First you lack proper error handling. If any function that can fail (like e.g. fopen) fails, you should act accordingly. If, for example you did
#include <error.h>
#include <errno.h>
...
f = fopen("game","wb");
if ( f == NULL ) {
error(1,errno,"File could not be opened");
}
...
You would have recieved an useful error message like
./game: File could not be opened: Text file busy
You printed a message, which is not even correct (the file not beeing able to be opened is somthing different, than not beeing found) and continued the program which resulted in a segmentation fault because you dereferenced the NULL pointer stored in f after the failure of fopen.
Second As the message tells us (at least on my linux machine), the file is busy. That means, that my operating system does not allow me to open the executable I'm running in write mode. The answers to this question lists numerous source of the explanation of this error message. There might be ways to get around this and open a running executable in write mode, but I doubt this is easy and I doubt that this would solve your problem because:...
Third Executable files are stored in a special binary format (usually ELF on Linux). They are not designed to be manually modified. I don't know what happens if you just append data to it, but you could run into serious problems if your not very careful and know what you're doing.
If you just try to store data, use another plain and fresh file. If you're hoping to append code to an executable, you really should gather some background information about ELF files (e.g. from man elf) before continuing.
These terms may not be 100% accurate, but I'm using the GCC compiler and POSIX library. I have C code compiled with the SQLite amalgamation file to a single executable.
In the user interface that exchanges JSON messages with the C program, I'd like to make it possible for users to copy the SQLite database files they create through the C program, and copy a full directory/folder.
Thus far, I've been able to rename and move files and folders programmatically.
I've read many questions and answers here, at Microsoft's C runtime library, and other places but I must be missing the fundamental points. I'm using regular old C, not C++ or C#.
My question is are there POSIX functions similar to rename(), _mkdir(), rmdir(), remove(), _stat(), that allow for programmatic copying of files and folders in Windows and Linux?
If not, can one just make a new folder and/or file and fread/fwrite the bytes from the original file to the new file?
I am primarily concerned with copying SQLite database files, although I wouldn't mind knowing the answer in general also.
Is this answer an adequate method?
Is the system() function a poor method? It seems to work quite well. However, it took awhile to figure out how to stop the messages, such as "copied 2 files" from being sent to stdout and shutting down the requesting application since it's not well-formed JSON. This answer explains how and has a link to Microsoft "Using command redirection operators". A /q in xcopy may or may not be necessary also, but certainly didn't do the job alone.
Thank you very much for any direction you may be able to provide.
The question that someone suggested as an answer and placed the little submission box on this question is one that I had already linked to in my question. I don't mean to be rude but, if it had answered my question, I would not have written this one. Thank you whoever you are for taking the time to respond, I appreciate it.
I don't see how that would be a better option than using system() because with the right parameters all the sub-directories and files of a single parent folder can be copied in one statement without having to iterate through all of them manually. Is there any reason why it would not be better to use system() apart from the fact that code will need to be different for each OS?
Handling errors are a bit different because system() doesn't return an errno but an exit code; however, the errors can be redirected from stderr to a file and pulled from there, when necessary
rename(): posix
_mkdir(): not posix. You want mkdir which is. mkdir takes two arguments, the second of which should usually be 077.
rmdir(): posix
remove(): posix
_stat(): not posix, you want stat() which is.
_stat and _mkdir are called as such on the Windows C library because they're not quite compatible with the modern Unix calls. _mkdir is missing an argument, and _stat looks like a very old version of the Unix call. You'll have trouble on Windows with files larger than 2GB.
You could do:
#ifdef _WIN32
int mkdir(const char *path, int mode) { return _mkdir(path); } /* In the original C we could have #defined this but that doesn't work anymore */
#define stat _stat64
#endif
but if you do so, test it like crazy.
In the end, you're going to be copying stuff with stdio; this loop works. (beware the linked answer; it has bugs that'll bite ya.)
int copyfile(const char *src, const char *dst)
{
const int bufsz = 65536;
char *buf = malloc(bufsz);
if (!buf) return -1; /* like mkdir, rmdir, return 0 for success, -1 for failure */
FILE *hin = fopen(src, "rb");
if (!hin) { free(buf); return -1; }
FILE *hout = fopen(dst, "wb");
if (!hout) { free(buf); fclose(hin); return -1; }
size_t buflen;
while ((buflen = fread(buf, 1, bufsz)) > 0) {
if (buflen != fwrite(buf, 1, buflen)) {
fclose(hout);
fclose(hin);
free(buf);
return -1; /* IO error writing data */
}
}
free(buf);
int r = ferror(hin) ? -1 : 0; /* check if fread had indicated IO error on input */
fclose(hin);
return r | (fclose(hout) ? -1 : 0); /* final case: check if IO error flushing buffer -- don't omit this it really can happen; calling `fflush()` won't help. */
}
I'm just learning D. Looks like a great language, but I can't find any info about the file I/O functions. I may be being dim (I'm good at that!), so could somebody point me in the right direction, please?
Thanks
Basically, you use the File structure from std.stdio.
import std.stdio;
void writeTest() {
auto f = File("1.txt", "w"); // create a file for writing,
scope(exit) f.close(); // and close the file when we're done.
// (optional)
f.writeln("foo"); // write 2 lines of text to it.
f.writeln("bar");
}
void readTest() {
auto f = File("1.txt"); // open file for reading,
scope(exit) f.close(); // and close the file when we're done.
// (optional)
foreach (str; f.byLine) // read every line in the file,
writeln(":: ", str); // and print it out.
}
void main() {
writeTest();
readTest();
}
What about the std.stdio module?
For stuff related specifically to files (file attributes, reading/writing a file in one go), look in std.file. For stuff that generalizes to standard streams (stdin, stdout, stderr) look in std.stdio. You can use std.stdio.File for both physical disk files and standard streams. Don't use std.stream, as this is scheduled for deprecation and doesn't work with ranges (D's equivalent to iterators).
Personally I find C-style file I/O favourable. I find it one of the most clear to use I/O's, especially if you work with binary files. Even in C++ I don't use streams, beside added safety it's just plain clumsy (much as I prefer printf over streams, excellent how D has a type-safe printf!).
I see that standard C has no way of telling if a file is already opened in another process. So the answer should contain several examples for each platform. I need that check for Visual C++ / Windows though.
Windows: Try to open the file in exclusive mode. If it works, no one else has opened the file and will not be able to open the file
HANDLE fh;
fh = CreateFile(filename, GENERIC_READ, 0 /* no sharing! exclusive */, NULL, OPEN_EXISTING, 0, NULL);
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE))
{
// the only open file to filename should be fh.
// do something
CloseHandle(fh);
}
MS says: dwShareMode
The sharing mode of an object, which can be read, write, both, delete, all of these, or none (refer to the following table).
If this parameter is zero and CreateFile succeeds, the object cannot be shared and cannot be opened again until the handle is closed.
You cannot request a sharing mode that conflicts with the access mode that is specified in an open request that has an open handle, because that would result in the following sharing violation: ERROR_SHARING_VIOLATION.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
extension:
how to delete a (not readonly) file filesystem which no one has open for read/write?
access right FILE_READ_ATTRIBUTES, not DELETE. DELETE could cause problems on smb share (to MS Windows Servers) - CreateFile will leave with a still open FileHandle /Device/Mup:xxx filename - why ever and whatever this Mup is. Will not happen with access right FILE_READ_ATTRIBUTES
use FILE_FLAG_OPEN_REPARSE_POINT to delete filename. Else you will delete the target of a symbolic link - which is usually not what you want
HANDLE fh;
fh = CreateFile(filename, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE /* no RW sharing! */, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_DELETE_ON_CLOSE, NULL);
if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE))
{
DeleteFile(filename); /* looks stupid?
* but FILE_FLAG_DELETE_ON_CLOSE will not work on some smb shares (e.g. samba)!
* FILE_SHARE_DELETE should allow this DeleteFile() and so the problem could be solved by additional DeleteFile()
*/
CloseHandle(fh); /* a file, which no one has currently opened for RW is delete NOW */
}
what to do with an open file? If the file is open and you are allowed to do an unlink, you will be left a file where subsequent opens will lead to ACCESS_DENIED.
If you have a temporary folder, then it could be a good idea to rename(filename, tempdir/filename.delete) and delete tempdir/filename.delete.
There's no way tell, unless the other process explicitly forbids access to the file. In MSVC, you'd do so with _fsopen(), specifying _SH_DENYRD for the shflag argument. The notion of being interested whether a file is opened that isn't otherwise locked is deeply flawed on a multitasking operating system. It might be opened a microsecond after you'd have found it wasn't. That's also the reason that Windows doesn't have a IsFileLocked() function.
If you need synchronized access to files, you'll need to add this with a named mutex, use CreateMutex().
Getting the open_files information is DIFFICULT, it's like pulling teeth, and if you don't have an immediate need for it you shouldn't be asking for "several examples for each platform" just for the hell of it. Just my opinion, of course.
Linux and many Unix systems have a system utility called lsof which finds open file handles and stuff. The way it does so is by accessing /dev/kmem, which is a pseudo-file containing a copy of "live" kernel memory, i.e. the working storage of the operating system kernel. There are tables of open files in there, naturally, and the memory structure is open-source and documented, so it's just a matter of a lot of busywork for lsof to go in there, find the information and format it for the user.
Documentation for the deep innards of Windows, on the other hand, is practically nonexistent, and I'm not aware that the data structures are somehow exposed to the outside. I'm no Windows expert, but unless the Windows API explicitly offers this kind of information it may simply not be available.
Whatever is available is probably being used by Mark Russinovich's SysInternals utilities; the first one that comes to mind is FileMon. Looking at those may give you some clues. Update: I've just been informed that SysInternals Handles.exe is even closer to what you want.
If you manage to figure that out, good; otherwise you may be interested in catching file open/close operations as they happen: The Windows API offers a generous handful of so-called Hooks: http://msdn.microsoft.com/en-us/library/ms997537.aspx. Hooks allow you to request notification when certain things happen in the system. I believe there's one that will tell you when a program –systemwide– opens a file. So you can make your own list of files opened for the duration you're listening to your hooks. I don't know for sure but I suspect this may be what FileMon does.
The Windows API, including the hook functions, can be accessed from C. Systemwide hooks will require you to create a DLL to be loaded alongside your program.
Hope these hints help you get started.
For Windows, this code works also:
boolean isClosed(File f) { return f.renameTo(f); }
An opened file can not be renamed, and a rename to same name does not cause another error. So if the rename succeeds, not having really done something, you know the file is not open.
Any such check would be inherently racy. Another process could always open the file between the point where you did the check and the point where you accessed the file.
The answers so far should tell you that finding out the information you've asked for is tricky, non-portable, and often inherently unreliable. So, from my perspective, the real answer is don't do that. Try to find a way to think about your real problem so that this question doesn't arise.
this can't be that hard guys.
do this:
try{
File fileout = new File(path + ".xls");
FileOutPutStream out = new FileOutPutStream(fileout);
}
catch(FileNotFoundException e1){
// if a MS Windows process is already using the file, this exception will be thrown
}
catch(Exception e){
}
You can use something like this. It is not a proper solution. But it works,
bool IsFileDownloadComplete(const std::wstring& dir, const std::wstring& fileName)
{
std::wstring originalFileName = dir + fileName;
std::wstring tempFileName = dir + L"temp";
while(true)
{
int ret = rename(convertWstringToString(originalFileName).c_str(), convertWstringToString(tempFileName).c_str());
if(ret == 0)
break;
Sleep(10);
}
/** File is not open. Rename to original. */
int ret = rename(convertWstringToString(tempFileName).c_str(), convertWstringToString(originalFileName).c_str());
if(ret != 0)
throw std::exception("File rename failed");
return true;
}
How can one create a new file descriptor from an existing file descriptor such that the new descriptor does not share the same internal file structure/entry in the file table? Specifically attributes such as file offset (and preferably permissions, sharing and modes) should not be shared between the new and old file descriptors.
Under both Windows and Linux, dup() will duplicate the file descriptor, but both descriptors still point to the same file structure in the process' file table. Any seeking on either descriptor will adjust the position for the other descriptors as well.
Note
I've since received answers for both Windows and Linux and adjusted the question a little too often, which has made it difficult for people to answer. I'll adjust my votes and accept the cleanest answer which covers both Windows and Linux. Apologies to all, I'm still new to the SO paradigm. Thanks for the great answers!
So basically, what you really want is to be given a file descriptor, and basically open the same file over again, to get a separate position, sharing, mode, etc. And you want to do this on Windows (where the "file descriptor" is basically a foreign object, not something used directly by the OS or the run-time library at all.
Amazingly enough, there is a way to do that, at least with MS VC++. All but two steps of it use only the Win32 API so porting to other compilers/libraries should be fairly reasonable (I think most supply versions of those two functions). Those are for converting a Unix-style file descriptor to a native Win32 file handle, and converting a native Win32 file handle back to a Unix-style file descriptor.
Convert file-descriptor to native file handle with _get_osfhandle()
Get a name for the file with GetFileInformationByHandleEx(FILE_NAME_INFO)1
Use CreateFile to open a new handle to that file
Create a file descriptor for that handle with _open_osfhandle()
Et voilà, we have a new file descriptor referring to the same file, but with its own permissions, position, etc.
Toward the end of your question, you make it sound like you also want the "permissions", but that doesn't seem to make any real sense -- the permissions attach to the file itself, not to how the file is opened, so opening or reopening the file has no effect on the file's permissions. If you really want to know the, you can get it with GetFileInformationByHandle, but be aware that file permissions in Windows are quite a bit different from the (traditional) file permissions in Unix. Unix has owner/group/world permissions on all files, and most systems also have ACLs (though there's more variation in how they work). Windows either has no permissions at all (e.g., files on FAT or FAT32) or else uses ACLs (e.g., files on NTFS), but nothing that's really equivalent to the traditional owner/group/world permissions most people are accustomed to on Unix.
Perhaps you're using "permissions" to refer to whether the file was open for reading, writing, or both. Getting that is considerably uglier than any of the preceding. The problem is that most of it is in the library, not Win32, so there's probably no way to do it that will be even close to portable between compilers. With MS VC++ 9.0 SP1 (not guaranteed for any other compiler) you can do this:
#include <stdio.h>
int get_perms(int fd) {
int i;
FILE * base = __iob_func();
for (i=0; i<_IOB_ENTRIES; i++)
if (base[i]._file == fd)
return base[i]._flag; // we've found our file
return 0; // file wasn't found.
}
Since this involved some spelunking, I wrote a quick test to verify that it might actually work:
#ifdef TEST
#include <io.h>
void show_perms(int perms, char const *caption) {
printf("File opened for %s\n", caption);
printf("Read permission = %d\n", (perms & _IOREAD)!=0);
printf("Write permission = %d\n", (perms & _IOWRT)!=0);
}
int main(int argc, char **argv) {
FILE *file1, *file2;
int perms1, perms2;
file1=fopen(argv[1], "w");
perms1 = get_perms(_fileno(file1));
fclose(file1);
file2=fopen(argv[1], "r");
perms2 = get_perms(_fileno(file2));
fclose(file2);
show_perms(perms1, "writing");
show_perms(perms2, "reading");
return 0;
}
#endif
And the results seem to indicate success:
File opened for writing
Read permission = 0
Write permission = 1
File opened for reading
Read permission = 1
Write permission = 0
You can then test that returned flag against _IOREAD, _IOWRT, and _IORW, which are defined in stdio.h. Despite my previous warnings, I should probably point out that I suspect (though I certainly can't guarantee) that this part of the library is fairly stable, so the real chances of major changes are probably fairly minimal.
In the other direction, however, there's basically no chance at all that it'll work with any other library. It could (but certainly isn't guaranteed to) work with the other compilers that use the MS library, such as Intel, MinGW or Comeau using MS VC++ as its back-end. Of those, I'd say the most likely to work would be Comeau, and the least likely MinGW (but that's only a guess; there's a good chance it won't work with any of them).
Requires the redistributable Win32 FileID API Library
So, I recommend reading up on this a little more. The dup() and related functions serve to create a duplicate value in the file descriptor table pointing to the same entry in the open file table. This is intended to have the same offset. If you call open(), you will create a new entry the open file table.
It doesn't make any sense to create a duplicate of a file descriptor and that new file descriptor have a different offset in the open file table (this seems to contradict what the word "duplicate" means).
I'm not sure what your question is actually. I mean, it isn't the same thing as a duplicate. You could read:
/proc/self/fd/[descriptor]
and get the string that was used to open that file descriptor; bear in mind this may provide some pitfalls, some of which you actually noted in your observation of calling open() again.
Maybe you can explain a little more and I can try to update to help.
Why don't you just open the file a second time with open() or CreateFile() on windows? This gives you all freedom of different access rights and separate offset.
This of course has the drawback that you you can not open the file exclusively, but it solves your problem very simply.