When I execute two C Programs in Linux, I can print their local/private file descriptor by using fileno(). It means, when I run two independent programs side by side, and print fileno() in each of them, 3 is printed for the first file opened, 4 is printed for the second file opened and so on.
Therefore, by using fileno(), it is not possible to know which input files are shared between them.
Is there any way to print the input file name that is shared between two C programs?
use
readlink /proc/<pid>/fd/* | sort -u > /tmp/process-<pid>.out
to create a file with a list of all files opened by a process with PID <pid>.
then use comm(1) to find the common files, as follows:
comm -12 /tmp/process-<pid1>.out /tmp/process-<pid2>.out
Note that this will list all files shared by these programs.
if you know that the specific file descriptors used by the program are e.g. 3,4,5,9,11,12, then replace the first command with:
readlink /proc/<pid>/fd/{3,4,5,9,11,12} | sort -u > /tmp/process-<pid>.out
If you don't know the file descriptors, and you want to assume that all the file descriptors which are open for read (including stdin) are input files, you'll have to do something more clever by reading /proc/<pid>/fdinfo/<file-descriptor>, which prints a flags field, which has that information.
Related
steps:
Let's say I have a C program inputFileName.c
I run inputFileName with input redirection such as ./inputFileName < file
How can I print the name of the file in my C program that I have typed in the terminal as an input redirection file?
The input redirection is a function of the shell. Your inputFileName executable see this as standard input. Depending on the exact operating system, you may be able to use system-specific functions to get the information you want, but there is not a standard means of doing so.
Input redirection can be achieved not only with the '<' symbol, but also with '|'.
program < filename
is equivalent to
cat filename | program
From there, one could go to
cat file1 file2 file3 | program
You begin to see why the initial 'stdin' for an executable cannot and does not have a "filename" associated with it.
If input comes from a pipe, there can't be an associated filename. Also if the file has been deleted or moved before closing the file descriptor, there is no associated filename. A file can have multiple names. In that case there are multiple filenames.
Given that, the "associated filename" of a file descriptor doesn't really make much sense. And even if you could get that info, using the filename in any way might make race conditions an issue.
The linux kernel does try to track an associated filename if a file descriptor was created by opening a file. But the keyword here is "tries".
If you are running Linux, you can find the filenname for standard input as a symlink under "/proc/self/fd/0". Just remember that you should not rely on that name for anything more than debug or display purposes.
In bash, If I have a file called file1 how can I use stdin along with the binary corresponding to the following code in order to return the integer file descriptor corresponding to file1 ?
int main(){
return fileno(stdin);
}
Thank you
p.s:
I'm looking for a bash expression like this:
user:~$expression | ./binary
p.s (bis):
I had some difficulties to make a synthetic title, please tell me if you find a better one
In bash, If I have a file called file1 how can I use stdin along with the binary corresponding to the following code in order to return the integer file descriptor corresponding to file1 ?
You have an apparent misconception. There is no single the file descriptor for any given file, nor indeed any file descriptor at all for a file that is not open. File descriptors are per-process resources associated in each process with that process's open files. The question is thus based on a false premise.
Furthermore, even if you redirect a process's standard input to come from file1, that does not identify stdin with file1 in that process. It merely means that you can read file1's contents via stdin, once. You cannot in that case gain any other information about file1 from stdin, so even in a more general sense, the methodology you propose to use to get information about file1 (other than its contents) is not viable.
I am writing a C program using some external binaries to achieve a planned goal. I need to run one command which gives me an output, which in turn I need to process, then feed into another program as input. I am using popen, but wonder if that is the same as using a KornShell (ksh) temporary file instead.
For example:
touch myfile && chmod 700
cat myfile > /tmp/tempfile
process_file < /tmp/tempfile && rm /tmp/tempfile
Since that creates a temporary file which can be readable by root, would it be the same if one used popen in C, knowing that pipes are also files? Or is it safe to assume that the Operating System (OS) will not allow any other process to read your pipe?
You say "that creates a temporary file which can be readable by root", which implies that you are attempting to transfer the data in a way in which the root user cannot read it. That's impossible; in general, the root user has total control of the system, and can thus read any data that is on the system, whether it's in a temporary file or not. Even within a single process, the root user can read the memory of that process.
If you use popen(), there will not be an entry for the file on a filesystem; it creates a pipe, which acts like a file, but doesn't actually write that data to disk, instead it just passes it between two programs.
There will be a file descriptor for it; depending on the system, it may be easier or harder to intercept that data, but it will always be possible to do so. For instance, on Linux, you can just look in /proc/<pid>/fd/ to find all of the open file descriptors and manipulate them (read from or write to them).
I am trying to redirect the output of a c program to file, even when it generates some errors because of problems with the input data. I can send the output but the error messages to a file.
Does somebody know how to do it?
From within C source code, you can redirect outputs using freopen():
General outputs:
freopen("myfile.txt", "w", stdout);
Errors:
freopen("myfile_err.txt", "w", stderr);
(This answer applies to bash shell, and similar flavors. You didn't specify your environment and this sort of question needs that detail.)
I assume you know about basic redirection with ">". To also capture STDERR in addition to STDOUT, use the following syntax:
command > file-name 2>&1
For some more background on standard streams and numbers:
http://en.wikipedia.org/wiki/Standard_streams#Standard_input_.28stdin.29
This depends on what you mean and what platform you are using. Very often you can accomplish this from the command line, which has been covered in another answer. If you use this method to accomplish this you should be aware that FILE * stderr is typically written immediately (unbuffered) while FILE * stdout may be buffered (usually line buffered) so you could end up with some of your error messages appearing to have been printed earlier than some other messages, but actually the other messages are just being printed late.
From within a C program you can also do something similar within the stdio system using freopen, which will effect the FILE *, so you could make fprintf(stderr, "fungus"); print to something besides what stderr normally would print to.
But if you want to know how to make a program redirect the actual file descriptors under a unix like system you need to learn about the dup and dup2 system calls. They allow you to duplicate a file descriptor.
int fd = open("some_file", O_WRONLY);
dup2(2,fd);
close(fd);
This code will make "some_file" the new stderr at the OS level. The dup2 call will close and replace file descriptor 2 (stderr, which is usually used by FILE * stderr but not necessarily if you call freopen(x,y,stderr) since that may make FILE *stderr use a different file descriptor).
This is how shell programs redirect input and output of programs. The open all of the files that the new program will need, fork, then the child uses dup2 to set up the files descriptors for the new program, then it closes any files that the new program won't need (usually just leaving 0, 1, and 2 open), and then uses one of the exec functions to become the program that the shell was told to run. (some of this isn't entirely accurate because some shells may rely on close on exe flags)
Using a simple linux command you can save the output into the file. here is a simple linux terminal command.
ls > file.txt
The output of this command will be stored into the file.
same as you can store the output of the program like this suppose, object file name is a, run the following command to save output in a file:
./a > file.txt
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.