_findfirst failure with .. path - c

Why _findfirst returns -1 with ..\*.txt search pattern
struct _finddata_t c_file;
hFile = _findfirst("..\\*.txt", &c_file);
But processes ..\* correctly?

_findfirst works correctly when passed "..\\*.txt". The fact that it returns -1 indicates that there are no text files in the directory above your working directory.

Our comments:
Are there any txt files in the current working directory of your process? – H2CO3
there are no txt files – Chesnokov Yuriy
That's why. From the documentation:
Provide information about the first instance of a file name that matches the file specified in the filespec argument.
No surprise, no magic.

Related

Program to compile files in a directory in openedge

Could someone help me in writing a program that has to compile all the files in the directory and report error, if any. For which my program has to get the list of all files under the folder with its full path and store it in a temp-table and then it has to loop through the temp table and compile the files.
Below is a very rough start.
Look for more info around the COMPILE statement and the COMPILER system handle in the online help (F1).
Be aware that compiling requires you to have a developer license installed. Without it the COMPILE statement will fail.
DEFINE VARIABLE cDir AS CHARACTER NO-UNDO.
DEFINE VARIABLE cFile AS CHARACTER NO-UNDO FORMAT "x(30)".
ASSIGN
cDir = "c:\temp\".
INPUT FROM OS-DIR(cDir).
REPEAT:
IMPORT cFile.
IF cFile MATCHES "*..p" THEN DO:
COMPILE VALUE(cDir + cFile) SAVE NO-ERROR.
IF COMPILER:ERROR THEN DO:
DISPLAY
cFile
COMPILER:GET-MESSAGE(1) FORMAT "x(60)"
WITH FRAME frame1 WIDTH 300 20 DOWN.
END.
END.
END.
INPUT CLOSE.
Since the comment wouldn't let me paste this much into it... using INPUT FROM OS-DIR returns all of the files and directories under a directory. You can use this information to keep going down the directory tree to find all sub directories
OS-DIR documentation:
Sometimes, rather than reading the contents of a file, you want to read a list of the files in a directory. You can use the OS–DIR option of the INPUT FROM statement for this purpose.
Each line read from OS–DIR contains three values:
*The simple (base) name of the file.
*The full pathname of the file.
*A string value containing one or more attribute characters. These characters indicate the type of the file and its status.
Every file has one of the following attribute characters:
*F — Regular file or FIFO pipe
*D — Directory
*S — Special device
*X — Unknown file type
In addition, the attribute string for each file might contain one or more of the following attribute characters:
*H — Hidden file
*L — Symbolic link
*P — Pipe file
The tokens are returned in the standard ABL format that can be read by the IMPORT or SET statements.

How can I search for a file within a directory and its sub-directories in c?

How can I search for a file within a directory and its sub-directories in C?
I'm not allowed to use find and I must use opendir , readdir and stat.
I want to perform something like the command ls -ln if the file indeed exists.
For traversing the directories, you will need: opendir(3), readdir(3), and closedir(3).
For checking the type of file (to see if it's a directory and if you should recursively search within it) you will need stat(2).
You will want to check
(struct stat).st_mode & S_IFDIR
to see if the file is a directory. See <sys/stat.h> for more information.
If we try to write a small piece of code in C then we can do this search activity easily.
Suppose you need to search abc.txt in a /home/Jack/ then just open a file stream and pass the file path as a parameter.
Now when this statement will be executed, it will try to open the existing file. This API will return non zero if the file exists otherwise it is returned -1 or zero.
You've already provided the basic answer: opendir/readdir/closedir. As you walk the directory entries, you check whether each refers to a file or a directory. Those that refer to directories, you traverse as well (typically recursively). For those that refer to files, you compare their names to the file(s) you're looking for, and see if you've found it.
One other minor detail: you probably also want to check for symbolic links. A symbolic link can (for example) refer to a parent directory, which could/can lead to infinite recursion. You may want to ignore symbolic links completely, or you may want to keep a list of directories you've already at least started to traverse, and resolve/traverse what's in the symbolic link only if it's not already in the list.

fopen() returning a NULL pointer, but the file definitely exists

The code I have is as follows:
FILE *txt_file = fopen("data.txt", "r");
if (txt_file == NULL) {
perror("Can't open file");
}
The error message returned is:
Can't open file: No such file or directory
The file 'data.txt' definitely exists in the working directory (it exists in the directory that contains my .c and .h files), so why is fopen() is returning a NULL pointer?
Standard problem. Try
FILE *txt_file = fopen("C:\\SomeFolder\\data.txt", "r");
I.e. try opening it with the full absolute path first ; if it works then you just have to figure out what the current directory is with _getcwd() and then fix your relative path.
Is it possible that the filename is not really "data.txt"?
On Unix, filenames are really byte strings not character strings, and it is possible to create files with controls such as backspace in their names. I have seen cases in the past in which copy-pasting into terminals resulted in files with ordinary-looking names, but trying to open the filename that appears in a directory listing results in an error.
One way to tell for sure that the filenames really are what you think they are:
$ python
>>> import os
>>> os.listdir('.')
My problem was that I had a file filename.txt and I didn't realize that in reality it was filename.txt.txt due to windows not showing the extension.
Make sure that your input file is in the same directory as the executable, which may be different than the one where your source files are kept. If you're running the program in an IDE debugger, make sure that your working directory is set to the location of the input file. Also, if you're running in *nix rather than Windows, you may need to prepend a "./" to the input filename.
Invisible SPACE character in file name?
Once a year I have a similar problem:
I try to open a file with the filename in a string, obtained from a sting operation. When I print the name it seems OK, but fopen() returns a null pointer. The only help is printing the name with delimiters showing the exact beginning and end of the filename string. Of course this does not not help with unprintable chars.
I just had a similar issue like this where I knew the path was correct and the file was in the right location. Check the file permissions. It is possible that the program cannot access the file because it is getting permission denied.
I encountered the same errno to fopen on Linux from a script file corrupted by Windows.
ENOENT 2 No such file or directory
Wordpad on Windows (or some other Microsoft culprit) inserted CRLF = (0x0D, 0x0A) into my linux script files in place of newline = LF = 0x0A. When I read the file name into a buffer and called fopen if failed due to the invisible appended CR character.
In the Codelite editor on Linux Mint I was able to show EOL characters (View > Display EOL) and remove them with find and replace, using copy and paste of the CRLF from the corrupted script files and the LF from an uncorrupted file into the text fields.

Getting the inode number of an unopen file from path

Is there a way I could get the inode number of a file which has not yet been opened. I would like to do this from inside a c function
Regards,
Lipika
Use stat(2) (which takes a file path), and check the st_ino field. Do note that it's possible for someone to move or remove the file between the time you call stat and whenever you manage to do anything with the information.
Essentially, the answer can be found in this question:
How do I read a directory as a file in Unix?
You have to read the directory which contains the file entry. That entry contains the inode number.
Unless you have very tight control over the permissions on every element of the path to the file, what you're trying to do is almost surely wrong. Between any two operations involving accessing a file by pathname, there is a race condition, i.e. the inode number you get is potentially incorrect even before the call (stat or readdir) that gives it to you returns. Why don't you want to open the file?

How to check whether two file names point to the same physical file

I have a program that accepts two file names as arguments: it reads the first file in order to create the second file. How can I ensure that the program won't overwrite the first file?
Restrictions:
The method must keep working when the file system supports (soft or hard) links
File permissions are fixed and it is only required that the first file is readable and the second file writeable
It should preferably be platform-neutral (although Linux is the primary target)
On linux, open both files, and use fstat to check if st_ino (edit:) and st_dev are the same. open will follow symbolic links. Don't use stat directly, to prevent race conditions.
The best bet is not to use filenames as identities. Instead, when you open the file for reading, lock it, using whatever mechanism your OS supports. When you then also open the file for writing, also lock it - if the lock fails, report an error.
If possible, open the first file read-only, (O_RDONLY) in LINUX. Then, if you try to open it again to write to it, you will get an error.
You can use stat to get the file status, and check if the inode numbers are the same.
Maybe you could use the system() function in order to invoke some shell commands?
In bash, you would simply call:
stat -c %i filename
This displays the inode number of a file. You can compare two files this way and if their inodes are identical, it means they are hard links. The following call:
stat -c %N filename
will display the file's name and if it's a symbolic link, it'll print the file name it links to as well. It prints out only one name, even if the file it points to has hard links, so checking the symbolic link would require comparing inode numbers for the 2nd file and the file the symbolic links links to in order to make sure.
You could redirect stat output to a text file and then parse the file in your program.
If you mean the same inode, in bash, you could do
[ FILE1 -ef FILE2 ] && echo equal || echo difference
Combined with realpath/readlink, that should handle the soft-links as well.

Resources