usage of tmpfile() in C - c

I don't understand why my script below seems to work without creating any files.
script.c:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]){
printf("P_tmpdir is '%s'\n", P_tmpdir);
FILE *tmp = tmpfile();
if(tmp == NULL){
printf("Unable to create temp file");
exit(1);
}
else{
printf("Temporary file is created\n");
}
for(int i = 0; string[i] != '\0'){
fputc(string[i], tmp);
}
rewind(tmp);
while(!feof(tmp)){
putchar(fgetc(tmp));
}
sleep(3);
return(0);
}
The P_tmpdir variable returns me the "/tmp" directory although in the sleeping time no new file is created in it... can you help me or explain me plz ?

Quoting cppreference.com (emphasis mine):
On some implementations (e.g. Linux), this function actually creates, opens, and immediately deletes the file from the file system: as long as an open file descriptor to a deleted file is held by a program, the file exists, but since it was deleted, its name does not appear in any directory, so that no other process can open it.
The file does not have to be "visible" in the file system tree, as long as a process has a handle on it, the file continues to exist.
If you want a file that's visible in the file system tree you should use mkstemp.

Related

Without using remove() function How to delete a file in C program

I am trying to delete a file in c program. Assume that the file is located in current directory of source file. I have searched a lot but didn't get any solution. Everyone is suggesting to use remove() function.
Here is my source code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
int delete_status;
char del[50];
printf("Enter a file name to delete it: ");
gets(del);
delete_status = remove(del);
if(delete_status!=0) {
printf("File can not be deleted!\nFile does not exist in current directory\n");
}
else printf("File %s has been deleted successfully!\n", del);
return 0;
}
Is there any way to remove file without using remove() function. I want to code manually without using any other stl built in function.
You can replace remove() with unlink() (for files) and rmdir() (for directories).
You can check this answer. You should try to read a system programming book where you can learn about uses like INTERNAL_SYSCALL.
You can skim through the functions referred in the posts like unlink() etc.
EDIT: actually somehow you will end up using a system-call at some level. You probably trying to achieve the operation of deleting a file from different abstraction level.(remove() system call will also use INTERNAL_SYSCALL which nothing but a system call).
Now from low level deleting a file doesn't mean we are erasing something. We are just considering the space as free space(free pool of memory) and then any metadata related to that file is also freed. To achieve that you need to implement a filesystem that allocates memory,deletes it..using device level instructions.
Call unlink for files, rmdir for directories. You could easily check which a file is using stat and then call the correct function.
struct stat sb;
if (!stat(filename, &sb))
{
if (S_ISDIR(sb.st_mode))
rmdir(filename);
else
unlink(filename);
}
Include <sys/stat.h> for stat and S_ISDIR, <unistd.h> for rmdir and unlink.
Oh, and per your comment:
All of you didn't understand my needs and requirement. I know that it is posible to delete a file using standard library function like remove(), unlink(), rm() etc. But I want to code manually without using any built in function.
Have fun reproducing unlink's source code.
I think what you need to know is unlink() function. For deleting files, remove() internally calls unlink() itself. Check the man page for details.
However, first I suggest you to change the gets() with fgets(). Also, int main() should be int main(void).
One can use fork and exec to run the rm command over shell.
sample code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int status;
pid_t pid = fork();
if(-1 == pid){
printf("fork() failed");
exit(EXIT_FAILURE);
}else if(pid == 0){
execl("/bin/sh", "sh", "-c", "rm /tmp/sandeep_reve.txt", (char *) NULL);
}else{
printf("Fork with id %ld\n",(long)pid);
waitpid(pid,&status,0);
}
return 0;
}
Use system():
PART I:(Delete file)
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
int delete_status;
char path[100],order[]="del ";//del for delete file, if change del to rd is delete folder(**Code at part 2)
printf("Enter a path of file to delete it: ");
gets(path);
strcat(order,path);//Order
fp = fopen(path,"r");
if(fp != NULL){//Check file whether or not exist
fclose(fp);
system(order);//Del file
printf("Delete successfully");
}else{
perror("ERROR");
fclose(fp);
}
return 0;
}
For example, you want to delete 1.txt.Then, you may put the c program in the same file and then intput 1.txt or enter whole path of the file.(e.g C:\User\desktop\1.txt)
PART II :(Delete folder)
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
int delete_status,i = 1;
char path[100],order[] = "rd ";//del -> rd
printf("Enter a path of file to delete it: ");
gets(path);
strcat(order,path);
system(order);
return 0;
}

Why are directory files not read using fread?

I was going through an example from Maurice Bach's Unix Book. He writes a simple copy program like mentioned below. However it fails when the inputfile is a directory file. I did stumble upon opendir and few other such API's - should I use that?
If a binary file can work with this, why is directory file considered different? In Unix, isn't everything abstracted as a file regardless of the way it is interpreted by the program.
Also how can I extend this program to support directory file and then create a mknod of that? I want to test this, suppose I am in /home/user1 and do a $./copy /home/user user-home-clone and mknod it to see how that directory will be different from home. I guess that the user-home-clone might not have a reference to itself, but all the other files in /home/user [ even though it would a file called user-home-clone would be there in /home/user ] since it was not there when we did the copy command?
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
char buffer[2048];
int copy(FILE *source, FILE *destination)
{
int count;
while ((count = fread(buffer, 1, sizeof buffer , source)) > 0)
{
fwrite(buffer, 1, count, destination);
}
return 0;
}
int main(int argc, char* argv[])
{
int status;
FILE *source;
FILE *destination;
if (argc != 3)
{
printf("%s takes exactly 3 arguments\n", argv[0]);
exit(1);
}
source = fopen(argv[1], "r");
if (source == NULL)
{
printf("%s can't be opened for reading\n", argv[1]);
exit(1);
}
destination = fopen(argv[2], "wb");
if (destination == NULL)
{
printf("%s can't be opened for writing\n", argv[2]);
exit(1);
}
if (copy(source, destination) == 0)
{
status = 0;
}
else
{
status = 1;
}
fclose(source);
fclose(destination);
exit(status);
}
I use Centos 6.5 Linux Ext4 Filesystem
In early versions of Unix, directory files could be read as binary files. However, when network and other types of virtual filesystems were added, this ability was removed, because different filesystems implement directories differently. While it would be technically possible for the driver to emulate a byte stream structure for these directories, it wasn't seen as a useful feature. Directories should be treated as opaque, abstract collections, and accessed using the directory-specific functions.

Linux/ Open directory as a file

I've been reading Brian Kernighan and Dennis Ritchie - The C Programming Language and chapter 8.6 is about directory listing under UNIX OS. They say that everything and even directory is a file. This means that I should be able to open directory as a file? I've tried it using stdio functions and it didn't work. Now, I'm trying it with UNIX system functions. Of course, I'm not using UNIX, I'm using Ubuntu linux. Here is my code:
#include <syscall.h>
#include <fcntl.h>
int main(int argn, char* argv[]) {
int fd;
if (argn!=1) fd=open(argv[1],O_RDONLY,0);
else fd=open(".",O_RDONLY,0);
if (fd==-1) return -1;
char buf[1024];
int n;
while ((n=read(fd,buf,1024))>0)
write(1,buf,n);
close (fd);
return 0;
}
This writes nothing even when argn is 1 (no parameters) and I'm trying to read current directory.
Any ideas/explanations? :)
Files are also called regular files to distinguish them from special files.
Directory or not a regular file. The most common special file is the directory. The layout of a directory file is defined by the filesystem used.
So use opendir to open diretory.
Nachiket's answer is correct (as indeed is sujin) but they don't clear up the mystery as to why open works and not read. Out of curiosity I made some changes to the given code to find out exactly what was going on.
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char* argv[]) {
int fd = -1;
if (argc!=1) fd=open(argv[1],O_RDONLY,0);
else fd=open(".",O_RDONLY,0);
if (fd < 0){
perror("file open");
printf("error on open = %d", errno);
return -1;
}
printf("file descriptor is %d\n", fd);
char buf[1024];
int n;
if ((n=read(fd,buf,1024))>0){
write(1,buf,n);
}
else {
printf("n = %d\n", n);
if (n < 0) {
printf("read failure %d\n", errno);
perror("cannot read");
}
}
close (fd);
return 0;
}
The result of compiling and running this:
file descriptor is 3
n = -1
read failure 21
cannot read: Is a directory
That settles it, though I'd have expected open to fail, since the correct system function for opening directories is opendir().
Though everything in unix is a file (directory also) but still filetype is concept is present in unix and applicable to all files.
there are file types like regular file,directory etc and certain operations and functions are allowed/present for every file type.
In your case readdir is applicable for reading contents of directory.
If you want to see the files in a directory you have to use the opendir and readdir functions.
K&R were correct for the original UNIX. I remember doing it back when UNIX file systems had a 14 character length limit for filenames. The opendir(), readdir(), ... stuff happened about the time that longer file names became common (around 1990?)

Print out file names and its' sizes in C

I'm not sure if C can do this, but I'm hoping that I can make a program that will look into a directory, and print out all of the contents of the directory along with the file size of each file. As in I wanted it to look like this (possibly):
filename.txt -- 300 bytes
filename2.txt -- 400 bytes
filename3.txt -- 500 bytes
And so on.
So far, I created a program that can open a file, and it will print the bytes, but it does not read the entire directory, and I have to be specific with which file I want to read.. (which is not what I want).
Here is what I have so far:
#include <stdio.h>
int main(){
FILE *fp; // file pointer
long fileSize;
int size;
// opens specified file and reads
fp = fopen( "importantcommands.txt", "rw" );
if( fp == NULL ){
printf( "Opening file error\n" );
return 0;
}
// uses fileLength function and prints here
size = fileLength(fp);
printf( "\n Size of file: %d bytes", size );
fclose(fp);
return 0;
}
int fileLength( FILE *f ){
int pos;
int end;
// seeks the beginning of the file to the end and counts
// it and returns into variable end
pos = ftell(f);
fseek (f, 0, SEEK_END);
end = ftell(f);
fseek (f, pos, SEEK_SET);
return end;
}
Please help.
C can certainly do it - the ls(1) command can, for example, and it's written in C.
To iterate over a directory, you can use the opendir(3) and readdir(3) functions. It's probably easier to just let the shell do it for you, though.
As far as getting the filename, you can just take it as a command line parameter by defining main as:
int main(int argc, char **argv)
Command line parameters will begin at argv[1].
See opendir() / fdopendir() and readdir() if you are using linux in dirent.h
man page
Simple example from a : SO Post
DIR *dir;
struct dirent *ent;
if ((dir = opendir ("c:\\src\\")) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
printf ("%s\n", ent->d_name);
}
closedir (dir);
}
else {
/* could not open directory */
perror ("Could not open directory");
return EXIT_FAILURE;
}
Also You can use the fstat() system call which can fill in the struct stat for any file you want. From that stat you can access that file's size.
Please use the man pages to help you out. (Almost) Everything related to Linux is insanely well documented.
To read a list of files in a directory look at opendir, readdir, closedir for Linux
use stat to get the length of the file.
These are of Linux
For winodws see http://msdn.microsoft.com/en-gb/library/windows/desktop/aa365200%28v=vs.85%29.asp and the link http://blog.kowalczyk.info/article/8f/Get-file-size-under-windows.html will show you how to do this.
To get the list of files in a directory look for "libc opendir". To get the size of a file without opening it you can use fstat.
This seems strangely similar to another question I saw recently. Anyway, here's my strangely similar answer (for Linux, not sure how it'll fare on Windows 7):
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
struct stat file_stats;
DIR *dirp;
struct dirent* dent;
dirp=opendir("."); // specify directory here: "." is the "current directory"
do {
dent = readdir(dirp);
if (dent)
{
printf("%s -- ", dent->d_name);
if (!stat(dent->d_name, &file_stats))
{
printf("%u bytes\n", (unsigned int)file_stats.st_size);
}
else
{
printf("(stat() failed for this file)\n");
}
}
} while (dent);
closedir(dirp);
}
There are little things need to be taken care for the given examples (under Linux or other UNIX).
You properly only want to print out the file name and size of a regular file only. Use S_ISREG() to test the st_mode field
If you want to recursively print out all files under sub directories also, you then need to use S_ISDIR() to test for direcotry and be carefull of special directory '.' and '..'.

SImple C Program opening a file

I'm trying to make a program to open a file, called "write.txt".
#include <stdio.h>
main() {
FILE *fp;
fp = fopen("write.txt", "w");
return 0;
}
Should this work? Because it returns nothing.
Other than an old variant of main, there's not really much wrong with that code. It should, barring errors, create the file.
However, since you're not checking the return value from fopen, you may get an error of some sort and not know about it.
I'd start with:
#include <stdio.h>
#include <errno.h>
int main (void) {
FILE *fp;
fp = fopen ("write.txt","w");
if (fp == NULL) {
printf ("File not created okay, errno = %d\n", errno);
return 1;
}
//fprintf (fp, "Hello, there.\n"); // if you want something in the file.
fclose (fp);
printf ("File created okay\n");
return 0;
}
If you're adamant that the file isn't being created but the above code says it is, then you may be a victim of the dreaded "IDE is working in a different directory from what you think" syndrome :-)
Some IDEs (such as Visual Studio) will actually run your code while they're in a directory like <solution-name>\bin or <solution-name>\debug. You can find out by putting:
system ("cd"); // for Windows
system ("pwd") // for UNIXy systems
in to your code to see where it's running. That's where a file will be created if you specify a relative path line "write.txt". Otherwise, you can specify an absolute path to ensure it tries to create it at a specific point in the file system.
What did you expect it to 'return' - it opens a file, on most platforms creating one if it doesn't exist.
You should probably fclose(fp) the file at the end.
I think you want to print the contents of file write.txt. (Assume it contains characters).
#include <stdio.h>
int main()
{
FILE *fp,char ch;
fp=fopen("write.txt","r");
if(fp==NULL)
{
printf("Some problem in opening the file");
exit(0);
}
else
{
while((ch=fgetc(fp))!=EOF)
{
printf("%c",ch);
}
}
fclose(fp);
return 0;
}
I think you should study some more fundamentals in C before you start attempting to work with files. A return means some data is passed back to the calling code from the called function.In this case you return 0 at the end of your program. You did not do anything with your FILE pointer except cause a new file to be created...

Resources