C Print what file is in the default stdin after using dup2 - c

I am writing a small shell in C that runs on Linux. Because there are a lot of dups involved, I would like to ask if there is a way to print what is inside position 0. For example if I call dup2(file_name,0) is there a way to print the file_name so I can use it for debugging?

If you are using linux operating system,you can show your file description table easily
every process on linux stored /proc/ directory by their process id, fd folder show file description table of process
e.g.
ls -l /proc/1405/fd

You can't get the filename from dup2. As you can read here it only returns a int value:
int dup2(int fildes, int fildes2);
What you can do in Linux is:
You can use readlink on /proc/self/fd/NNN where NNN is the file
descriptor. This will give you the name of the file as it was when it
was opened [here]
Or something more creative is creating a struct where you can assosiate the fildes to a filename.
Something like this:
struct Files{
int fildes;
char filename[50];
} files;
If you have more then one just create an array and take the one you need every time; in such a way you can always map it with a filename.

Related

How to know which input files are shared between two C programs?

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.

In bash, how to use stdin to pass a stream (corresponding to a file) to a C binary?

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.

auto delete file on linux

I am trying to do a file be deleted when a program ends. I remember that before I could put the unlink() before the first close() and I don't need reopen the file.
What I expect: The file is erased after the program ends.
What is happening: The file is erased when the call to unlink happens the file is erased.
My sample program:
int main()
{
int fd = open(argv[1], O_CREAT);
int x = 1;
write(fd, "1234\n", 5);
close(fd);
fd = open(argv[1], 0);
unlink(argv[1]);
while (x <= 3)
{
int k;
scanf(" %d", &k);
x++;
}
close(fd);
return 0;
}
Has a way that I can open() the file, interact with it and on close() delete the file from harddisk? I'm using fedora linux 18.
I need know the name of the file that I did open in this way because it will be used by another application.
Unlinking a file simply detaches the file name from the underlying inode, making it impossible to open the file using that file name afterwards.
If any process has the file still open, they can happily read and write it, as those operations operate on the inode and not the file name. Also, if there are hardlinks (other file names referring to the same inode) left, those other file names can be used to open the file just fine. See e.g. the Wikipedia article on inodes for further details.
Edited to add:
In Linux, you can leverage the /proc pseudofilesystem. If your application (with process ID PID) has file descriptor FD open, with the file name already unlinked, it can still let another application work on it by telling the other application to work on /proc/PID/fd/FD. It is a pseudo-file, meaning it looks like a (non-functioning!) symlink, but it is not -- it's just useful Linux kernel magic: as long as the other application just opens it normally (open()/fopen() etc., no lstat()/readlink() stuff), they will get access as if they were opening a normal file.
As a real-world example, open two terminals, and in one write
bash -c 'exec 3<>foobar ; echo $$ ; rm foobar ; echo "Initial contents" >&3 ; cat >&3'
The first line it outputs is the PID, and FD is 3 here. Anything you type (after pressing Enter) will be appended to a file that was briefly named foobar, but no longer exists. (You can easily verify that.)
In a second terminal, type
cat /proc/PID/fd/3
to see what that file contains.
It sounds like what you really want is tmpfile():
The tmpfile() function opens a unique temporary file in binary
read/write (w+b) mode. The file will be automatically deleted when it
is closed or the program terminates.
The File is unlinked, so it won't show up from ls... but the file still exists there is an inode and you could actually re-link it... the file won't be removed from the disk until all file descriptors pointing to it are closed...
you could still read and write to the fd while it is open after it is unlinked...

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.

How do you get the filename of a tempfile to use in Linux?

Let's say I'm creating a program in C that needs to use a tempfile. Creating an ad hoc tempfile in /tmp is probably not a good idea. Is there a function or OS call to supply me with a tempfile name so that I can begin to write and read from it?
You can use the mkstemp(3) function for this purpose. Another alternative is the tmpfile(3) function.
Which one of them you choose depends on whether you want the file to be opened as a C library file stream (which tmpfile does), or a direct file descriptor (mkstemp). The tmpfile function also deletes the file automatically when you program finishes.
The advantage of using these functions is that they avoid race conditions between determining the unique filename and creating the file -- so that two programs won't try to create the same file at the same time, for example.
See the man pages for both functions for more details.
The question is how to generate a temporary file name. Neither mkstemp nor tmpfile provide the caller with a name, they return a file descriptor or file handle, respectively.
#garethm:
I believe that the function you're looking for is called tmpnam.
You should definitely not use tmpnam. It suffers from the race condition problem I mentioned in my answer: Between determining the name and opening it, another program may create the file or a symlink to it, which is a huge security hole.
The tmpnam man page specifically says not to use it, but to use mkstemp or tmpfile instead.
Absolutely: man mkstemp.
The man page has example usage.
Not sure about anything in a C lib, but you can do this at the shell with mktemp.
You should use the mkstemp() as this is the recommended function, but it returns a file descriptor, so once you have the descriptor get it's name:
int fd;
fd = mkstemp("hdrXXXXXX);
/* Read out the link to our file descriptor. */
sprintf(path, "/proc/self/fd/%d", fd);
memset(result, 0, sizeof(result));
readlink(path, result, sizeof(result)-1);
/* Print the result. */
printf("%s\n", result);
usually there's no need to actually make a named file; instead use the file descriptor path,
FILE *tmp=tmpfile();
char path[PATH_MAX+1]={0};
sprintf(path, "/dev/fd/%d", fileno(tmp));
printf("%s\n", path);

Resources