If I try to open an invalid TIFF file with TIFFOpen(), the function returns NULL. For some reason, the error handler isn't called. However, the file remains open, so I can't delete/overwrite it from the same process.
I tried using TIFFFdOpen(), so that I can close the handle myself, but for some reason it gives me this error on valid TIFFs: "Cannot read TIFF header". This time the error is passed via the error handler.
How can I solve either of these problems?
Update: I'm talking about problems in TIFFOpen() itself, not in functions called later on. For example, they might occur if the TIFF file has size zero.
Perhaps you have an old or broken libtiff? I tried with libtiff-3.8.2 and it seems to work OK:
$ head -c 1000000 sample.tif > broken.tif
$ tiffinfo broken.tif
TIFFReadDirectory: broken.tif: Can not read TIFF directory count.
$ strace tiffinfo broken.tif
...
open("broken.tif", O_RDONLY) = 3
...
write(2, "broken.tif: Can not read TIFF dir"...
...
close(3) = 0
exit_group(0) = ?
Ie. there's a sane error and no leak (explicit close before the exit). I get the same behaviour with my own code.
Related
I'm working on an assignment that involves creating files and manipulating characters within them using what the lecturer describes as "File and System I/O calls" in C.
Specifically, I am using open, creat, read, write, lseek, close, and unlink.
Without revealing too much and violating academic integrity, essentially the assignment just entails creating files, copying characters between them, changing the characters, etc.
All of this was going perfectly until a certain point of the program after which read just... Wouldn't work. It doesn't matter what file I am accessing, or what other calls I put before it- for instance, I have tried closing and re-opening a file before trying to read, writing before reading (worked perfectly, put the characters right at the file position the lseek intended), etc.
I have checked the returns of all previous commands, none are giving errors other than the read, which is giving me errorno 9. Having looked this up, it appears to refer to having an incorrect file descriptor, but this doesn't make sense to me as I can use the same fid for any other command. Using ls -l, I confirmed that I have read and write permission (groups and public do not, if that helps).
I am at a total loss of where to go troubleshooting from here, any help would be immensely appreciated. Here is the code snippet in question:
readStatus = lseek(WWWfid,500,0);
if (readStatus<0) {
printf("error with lseek");
return 0;
}
/*printf("Read status: %i\n", readStatus);/*DEBUG*/
writeStatus = write(WWWfid, "wtf", 3);
if (writeStatus<0) {
printf("error with write");
return 0;
}
readStatus = read(WWWfid, buffer, 26);
int errorNum = errno;
/*buffer[27] = '\0';*/
if (readStatus<0) {
printf("error with read before loop, error %i\n", errorNum);
return 0;
}
I can likely include more without invoking the wroth of my uni but I'd prefer not to- also seems likely to be irrelevant given that all proceeding code appears to be functioning correctly.
Thanks for reading, please let me know if you have any insight at all
In a script I often call the function Rcplex(), which prints "CPLEX environment opened" and "Closed CPLEX environment" to the console. Since the function is called rather frequently, it prints this very often, which is quite annoying. Is there a way to suppress this? I tried sink(), suppressWarnings/Messages or invisible(catch.output()) but none of these did the trick. I proceeded to check the code of Rcplex() and found where the printing to the console happens. Rcplex() calls an underlying C-function (Rcplex.c). In the code of rcplex.c I located the commands which cause the printing:
REprintf("CPLEX environment opened\n");
REprintf("Closed CPLEX environment\n");
Is there a way to capture the output from REprintf() so that it does not get printed to the R-console? One way would obviously be to mess around with the Rcplex.c file and delete the corresponding lines. However, this would not be a very clean solution, which is why I'm asking for another way to capture the output from C-functions.
You had problems using sink() and capture.output() normally because sink() does not redirect output from REprintf, as we see in comments from the source code for REprintf:
/* =========
* Printing:
* =========
*
* All printing in R is done via the functions Rprintf and REprintf
* or their (v) versions Rvprintf and REvprintf.
* These routines work exactly like (v)printf(3). Rprintf writes to
* ``standard output''. It is redirected by the sink() function,
* and is suitable for ordinary output. REprintf writes to
* ``standard error'' and is useful for error messages and warnings.
* It is not redirected by sink().
However, we can use type = "message" to deal with this; from help("capture.output"):
Messages sent to stderr() (including those from message, warning and
stop) are captured by type = "message". Note that this can be "unsafe" and should only be used with care.
First I make a C++ function with the same behavior you're dealing with:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericVector example_function(NumericVector x) {
REprintf("CPLEX environment opened\n");
REprintf("Closed CPLEX environment\n");
// As mentioned by Dirk Eddelbuettel in the comments,
// Rcpp::Rcerr goes into the same REprintf() stream:
Rcerr << "Some more stuff\n";
return x;
}
If I call it from R normally, I get:
example_function(42)
CPLEX environment opened
Closed CPLEX environment
Some more stuff
[1] 42
However, I could instead do this:
invisible(capture.output(example_function(42), type = "message"))
[1] 42
And while the output is is printed to the console, the message is not.
Warning
I would be remiss if I didn't mention the warning from the help file I quoted above:
Note that this can be "unsafe" and should only be used with care.
The reason is that this will eliminate all output from actual errors as well. Consider the following:
> log("A")
Error in log("A") : non-numeric argument to mathematical function
> invisible(capture.output(log("A"), type = "message"))
>
You may or may not want to therefore send the captured output to a text file in case you have to diagnose something that went wrong. For example:
invisible(capture.output(log("A"), type = "message", file = "example.txt"))
Then I don't have to see the message in the console, but if I need to check example.txt afterward, the message is there:
Error in log("A") : non-numeric argument to mathematical function
I am facing this strange problem.
To delete a file unlink() API is called in my code. This call removes the file and succeeds on non-windows platforms. On windows it succeeds (returns 0) but doesn't remove the file.
To experiment I added a loop to call same API repeatedly. In second iteration I got an Permission denied error, Error code =13. Though read/write attributes are set on file and program has full permission to access the file.
I then called DeleteFile() instead of unlink() API. To my surprise I see the same result,call succeeded i.e. returned 1 but file is not removed physically.
I checked through unlocker utility, no other program is accessing the file except the program which is trying to remove this file.
Does anyone has idea what else could be wrong ?
Edit1:
Just to ensure file was not opened at the time of removing it. I saved the handle when file was created and tried to close before removing the file but I got error "'UNOPENED' (Errcode: 9 - Bad file descriptor)". Thus I conclude the file was not open at the time of removing it.
Edit2
As requested, here is the simplified version of code used to create and remove the file.
// Code to create the file
int create_file(const char* path)
{
HANDLE osfh; /* OS handle of opened file */
DWORD fileaccess; /* OS file access (requested) */
DWORD fileshare; /* OS file sharing mode */
DWORD filecreate; /* OS method of opening/creating */
DWORD fileattrib; /* OS file attribute flags */
SECURITY_ATTRIBUTES SecurityAttributes;
SecurityAttributes.nLength= sizeof(SecurityAttributes);
SecurityAttributes.lpSecurityDescriptor= NULL;
SecurityAttributes.bInheritHandle= !(oflag & _O_NOINHERIT);
fileaccess= GENERIC_WRITE;
fileshare= FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
filecreate= CREATE_NEW;
if ((osfh= CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
filecreate, fileattrib, NULL)) == INVALID_HANDLE_VALUE)
{
// error handling
}
}
//Code to delete the file -
int remove_file (const char* name)
{
if ((err = unlink(name)) == -1)
{ //Error handling }
}
Edit3
As pointed by Joachim Pileborg and icabod, that DeleteFile() does not remove file if it is still open. As suggested by Remy Lebeau, to use process explorer. I found that one handle to file was indeed open when I closed that from process explorer file deleted like a charm :)
I had also mentioned in the Edit1 when I tried to close the file I got an error. It happened because the file descriptor I get from createfile() is not the actual handle returned by CreateFile() API instead a logical mapped handle due to underlying code complexities to support other non-windows platforms. Anyways, now I understood the root cause of problem but I was expecting if a file with open handle is passed to DeleteFile() API then it should fail in first attempt rather succeed and wait for open handles to close.
Assuming that you call your Createfile function, then later call your remove_file function... you still have a handle open to the file. The WinAPI function CreateFile, if it succeeds, keeps a handle open on the file. In your provided code, you don't close that handle.
From the documentation on DeleteFile:
The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.
My guess is that you still have a handle open, and when you close that handle the file will be deleted.
However, your sample code is incomplete, so it is difficult to tell.
My program calls exec() on a binary that has been written to a directory specified by the user. If the directory resides in a tree mounted with "noexec", the exec() fails with EACCES.
Instead of failing the exec(), I would like to be able to figure out if a directory was mounted with noexec, but none of fcntl(), stat() or mount() return this info (from reading the manpages). Looking at the kernel source for the exec system call, it looks like this info is stored in the metadata of the inode, and I don't see this info being returned from any system call.
673 struct nameidata nd;
(..)
677 err = path_lookup_open(AT_FDCWD, name, LOOKUP_FOLLOW, &nd, FMODE_READ|FMODE_EXEC);
678 file = ERR_PTR(err);
(..)
682 file = ERR_PTR(-EACCES);
683 if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
684 S_ISREG(inode->i_mode)) {
Does anyone know of a way to do this?
Thanks.
You can use statvfs()
struct statvfs st;
inr rc = statvfs("/mnt/foo", &st);
if (rc == -1)
error();
if (st.f_flag & ST_NOEXEC) {
//no exec flags was set
}
Did you consider reading /proc/mounts then determining which file system your program binary resides on, perhaps using statfs(2) and/or realpath(3)?
But you always should care about, and handle, the failure of execve(2) and related exec functions, which can fail for a variety of reasons.
There are many ways execve can fail, and some of them are not easily reproducible; likewise for the failure of fork or any other syscall.
I would either leave and report the EACCESS error (of execve), or, if you absolutely want to catch & explain more the noexec mount option, do the more complex thing (statfs and/or realpath and scanning of /proc/mounts or /proc/self/mounts) after such an EACCESS failure.
There is no much point in testing a binary path before execve-ing it ... just report the error after...
I have a C application running on Linux and it processes thousands of messages...but not whe I run the application after a couple minutes it brings up the following error:
sh: error while loading shared libraries: libc.so.6: cannot open shared object file: Error 24
The application is doing about 30 messages per seconds, could it be some file open handle issue?
STDOUT receives: "Process 19374 received signal 11 "
Any ideas?
Thanks for the help ;-)
Lynton
Errno 24 means: "Too many open files".
After some thoughts I think the application opens a file, which is not allowed by the system anymore. The application can not handle this situation correctly, and crashes with a segmentation fault. Are the return values from the "open" system call checked correctly everywhere?
To handle this situation, I found 2 ways to resolve it. Either to work on same alloted file descriptor number or close FD just after their work have been done.