File Copy using filp_open - c

I want to make the syscall using filp_open!!
purpose is file copy!!
but a problem is that i can't find end of file.
opersting system is redhat9 and kernel version is 2.6.32!!
i want to help to me plz!!!!
#include <linux/kernel.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#define BUF_SIZE 4096
asmlinkage int sys_forensiccopy(char *src, char *dst)
{
struct file *input_fd;
struct file *output_fd;
size_t ret_in, ret_out; /* Number of bytes returned by read() and write() */
char buffer[BUF_SIZE]={0,}; /* Character buffer */
int ret;
int i;
mm_segment_t old_fs;
/* Create input file descriptor */
input_fd = filp_open(src, O_RDONLY, 0);
if (input_fd == -1) {
printk ("[!] Can not open the src file");
return 2;
}
/* Create output file descriptor */
output_fd = filp_open(dst, O_WRONLY|O_CREAT, 0644);
if(output_fd == -1){
printk("[!] Can't crate the dstfile");
return 3;
}
old_fs=get_fs();
set_fs(get_ds());
printk("%d\n", input_fd->f_op->read(input_fd,buffer,BUF_SIZE,&input_fd->f_pos));
set_fs(old_fs);
/* Close file descriptors */
filp_close(input_fd,0);
filp_close(output_fd,0);
return 0;
}

Related

Is the "mmap tutorial" incorrect, or does GCC miscompile it?

This mmap tutorial from 15 years ago ranks high in Google searches, but it actually runs subtly incorrectly on my Linux system.
mmap_write.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define FILEPATH "/tmp/mmapped.bin"
#define NUMINTS (1000)
#define FILESIZE (NUMINTS * sizeof(int))
int main(int argc, char *argv[])
{
int i;
int fd;
int result;
int *map; /* mmapped array of int's */
/* Open a file for writing.
* - Creating the file if it doesn't exist.
* - Truncating it to 0 size if it already exists. (not really needed)
*
* Note: "O_WRONLY" mode is not sufficient when mmaping.
*/
fd = open(FILEPATH, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
if (fd == -1) {
perror("Error opening file for writing");
exit(EXIT_FAILURE);
}
/* Stretch the file size to the size of the (mmapped) array of ints
*/
result = lseek(fd, FILESIZE-1, SEEK_SET);
if (result == -1) {
close(fd);
perror("Error calling lseek() to 'stretch' the file");
exit(EXIT_FAILURE);
}
/* Something needs to be written at the end of the file to
* have the file actually have the new size.
* Just writing an empty string at the current file position will do.
*
* Note:
* - The current position in the file is at the end of the stretched
* file due to the call to lseek().
* - An empty string is actually a single '\0' character, so a zero-byte
* will be written at the last byte of the file.
*/
result = write(fd, "", 1);
if (result != 1) {
close(fd);
perror("Error writing last byte of the file");
exit(EXIT_FAILURE);
}
/* Now the file is ready to be mmapped.
*/
map = mmap(0, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
close(fd);
perror("Error mmapping the file");
exit(EXIT_FAILURE);
}
/* Now write int's to the file as if it were memory (an array of ints).
*/
for (i = 1; i <=NUMINTS; ++i) {
map[i] = 2 * i;
}
/* Don't forget to free the mmapped memory
*/
if (munmap(map, FILESIZE) == -1) {
perror("Error un-mmapping the file");
/* Decide here whether to close(fd) and exit() or not. Depends... */
}
/* Un-mmaping doesn't close the file, so we still need to do that.
*/
close(fd);
return 0;
}
mmap_read.c:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define FILEPATH "/tmp/mmapped.bin"
#define NUMINTS (1000)
#define FILESIZE (NUMINTS * sizeof(int))
int main(int argc, char *argv[])
{
int i;
int fd;
int *map; /* mmapped array of int's */
fd = open(FILEPATH, O_RDONLY);
if (fd == -1) {
perror("Error opening file for reading");
exit(EXIT_FAILURE);
}
map = mmap(0, FILESIZE, PROT_READ, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
close(fd);
perror("Error mmapping the file");
exit(EXIT_FAILURE);
}
/* Read the file int-by-int from the mmap
*/
for (i = 1; i <=NUMINTS; ++i) {
printf("%d: %d\n", i, map[i]);
}
if (munmap(map, FILESIZE) == -1) {
perror("Error un-mmapping the file");
}
close(fd);
return 0;
}
If the file does not already exist, the output of mmap_read is
...
998: 1996
999: 1998
1000: 2000
But if it does, the output is
...
998: 1996
999: 1998
1000: 0
Should the author have flushed the write? Or is GCC miscompiling the code?
Edit: I noticed that it's the prior existence or non-existence of the file that makes a difference, not the compilation flag.
You are starting at the second element, and writing 2000 after the end of the map.
for (i = 1; i <=NUMINTS; ++i) {
map[i] = 2 * i;
}
should be
for (i = 0; i < NUMINTS; ++i) {
map[i] = 2 * ( i + 1 );
}
Demo
It's not a buffering issue. write is a system call, so the data passed to the OS directly. It doesn't mean the data has been written to disk when write returns, but it is in the OS's hands, so it's as if it was on disk as far as OS functions are concerned, including its memory-mapping functionality.
In C indexes are from zero. Writing and reading index 1000 you invoke undefined behaviour
Change to in the write.:
for (i = 1; i <=NUMINTS; ++i) {
map[i - 1] = 2 * i;
}
and reading to:
for (i = 1; i <=NUMINTS; ++i) {
printf("%d: %d\n", i, map[i-1]);
}

getting spaces while writing a text fileusing file operation in c

I am trying to write some data into the file line by line and then reading each data separatly line by line from the source file and writing it to another file.
But while writing data to destination file , I am getting spaces.
I mean the data is being written after multiple spaces.
I am using fgets instead of fread.
/*
* ======== fatsd.c ========
*/
#include <file.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <third_party/fatfs/ffcio.h>
#include <ti/display/Display.h>
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SDFatFS.h>
#include <ti/drivers/UART.h>
/* Example/Board Header files */
#include "Board.h"
/* Buffer size used for the file copy process */
#ifndef CPY_BUFF_SIZE
#define CPY_BUFF_SIZE 2048
#endif
/* String conversion macro */
#define STR_(n) #n
#define STR(n) STR_(n)
/* Drive number used for FatFs */
#define DRIVE_NUM 0
int i= 20;
int x;
char con_buff[100];
const char inputfile[] = "fat:"STR(DRIVE_NUM)":input1.txt";
const char outputfile[] = "fat:"STR(DRIVE_NUM)":output.txt";
const char copyfile[] = "fat:"STR(DRIVE_NUM)":copy2.txt";
char textarray[] = "Jan 1 2017 00:00:00 75 822 96 548 85 76 82 93 78 82 64 89";
char text[]="ram sham heloo bye";
char cpy[]="\r\n";
static Display_Handle display;
/* File name prefix for this filesystem for use with TI C RTS */
char fatfsPrefix[] = "fat";
//unsigned char cpy_buff[CPY_BUFF_SIZE + 1];
char cpy_buff[CPY_BUFF_SIZE + 1];
char mybuff[CPY_BUFF_SIZE + 1];
/*
* ======== mainThread ========
* Thread to perform a file copy
*
* Thread tries to open an existing file inputfile[]. If the file doesn't
* exist, create one and write some known content into it.
* The contents of the inputfile[] are then copied to an output file
* outputfile[]. Once completed, the contents of the output file are
* printed onto the system console (stdout).
*/
void *mainThread(void *arg0)
{
SDFatFS_Handle sdfatfsHandle;
/* Variables for the CIO functions */
FILE *src, *dst,*new;
/* Variables to keep track of the file copy progress */
unsigned int bytesRead = 0;
unsigned int bytesWritten = 0;
unsigned int filesize;
unsigned int totalBytesCopied = 0;
/* Call driver init functions */
GPIO_init();
SDFatFS_init();
/* Configure the LED pin */
GPIO_setConfig(Board_GPIO_LED0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
/* add_device() should be called once and is used for all media types */
add_device(fatfsPrefix, _MSA, ffcio_open, ffcio_close, ffcio_read,
ffcio_write, ffcio_lseek, ffcio_unlink, ffcio_rename);
/* Turn on user LED */
GPIO_write(Board_GPIO_LED0, Board_GPIO_LED_ON);
strcpy(con_buff,"This example requires a FAT filesystem on the SD card.\r\n"
"You will get errors if your SD card is not formatted with a filesystem.\r\n");
puts(con_buff);
/* Mount and register the SD Card */
sdfatfsHandle = SDFatFS_open(Board_SDFatFS0, DRIVE_NUM);
if (sdfatfsHandle == NULL)
{
strcpy(con_buff,"Error starting the SD card\n");
puts(con_buff);
x=1;
while (1);
}
else
{
strcpy(con_buff,"Drive is mounted\n");
x=2;
}
/* Try to open the source file */
src = fopen(inputfile, "a");
if (!src)
{
strcpy(con_buff,"Creating a new file ...");
puts(con_buff);
x=3;
/* Open file for both reading and writing */
src = fopen(inputfile, "w+");
if (!src)
{
strcpy(con_buff,"Error:could not be created.\nPlease check the Board.html if additional jumpers are necessary.check if sd card is inserted correctly\n"
"Aborting... \n");
puts(con_buff);
x=4;
while (1);
}
x=5;
/* Reset the internal file pointer */
rewind(src);
}
else {
fseek(src, 0, SEEK_END);
filesize = ftell(src);
if(filesize!=0)
{
fwrite(cpy, 1, strlen(cpy), src);
}
fwrite(textarray, 1, strlen(textarray), src);
fwrite(cpy, 1, strlen(cpy), src);
fwrite(text, 1, strlen(text), src);
fwrite(cpy, 1, strlen(cpy), src);
fwrite(textarray, 1, strlen(textarray), src);
fwrite(cpy, 1, strlen(cpy), src);
fwrite(text, 1, strlen(text), src);
x=6;
}
fflush(src);
fclose(src);
/* Create a new file object for the file copy */
dst = fopen(outputfile, "w");
new = fopen(copyfile, "a");
src = fopen(inputfile, "r");
if(!new)
{
strcpy(con_buff,"Error opening new file ");
puts(con_buff);
}
if (!dst)
{
strcpy(con_buff,"Error opening \"%s\"\n"
"Aborting...\n");
puts(con_buff);
x=7;
while (1);
}
else {
strcpy(con_buff,"Starting file copy\n");
puts(con_buff);
x=8;
}
/* Copy the contents from the src to the dst */
while (!feof(src))
{
fgets(cpy_buff,sizeof(cpy_buff),src); //READ FROM FILE
/* Read from source file */
puts(cpy_buff);
i=i+1;
fwrite(cpy_buff, 1,sizeof(cpy_buff),dst); //PUBLISH
strcpy(cpy_buff,"\0");
}
fflush(dst);
/* Get the filesize of the source file */
fseek(src, 0, SEEK_END);
filesize = ftell(src);
sprintf(con_buff,"size of file is %d",filesize);
puts(con_buff);
/* Close both inputfile[] and outputfile[] */
fclose(src);
fclose(dst);
fclose(new);
sprintf(con_buff,"File \"%s\" (%u B) copied to \"%s\" (Wrote %u B)\n",inputfile, filesize, outputfile, totalBytesCopied);
puts(con_buff);
/* Now output the outputfile[] contents onto the console */
/* Stopping the SDCard */
SDFatFS_close(sdfatfsHandle);
sprintf(con_buff,"Drive %u unmounted\n", DRIVE_NUM);
puts(con_buff);
return (NULL);
}
/*
* ======== fatfs_getFatTime ========
*/
int32_t fatfs_getFatTime(void)
{
/*
* FatFs uses this API to get the current time in FatTime format. User's
* must implement this function based on their system's timekeeping
* mechanism. See FatFs documentation for details on FatTime format.
*/
/* Jan 1 2017 00:00:00 */
return (0x4A210000);
}
regarding statements like:
fwrite(cpy_buff, 1,sizeof(cpy_buff),dst);
This will write the whole buffer, even though most of the trailing bytes of the buffer cpy_buff are garbage. Suggest:
fwrite(cpy_buff, 1,strlen(cpy_buff),dst);

Reading and writing pdf or binary data in C

I'm implementing ftp and I want to upload and download files, when I download or upload pdf files they are corrupted. How can handle reading any file, using read() and write() or mmap? below is my simplified code of what I have tried.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int is_regular_file(const char *path)
{
struct stat path_stat;
stat(path, &path_stat);
return (S_ISREG(path_stat.st_mode));
}
int ft_get_file_size(const char *filename)
{
struct stat file;
int fd;
if (!is_regular_file(filename))
return (-1);
fd = open(filename, O_RDONLY);
memset(&file, 0, sizeof(struct stat));
fstat(fd, &file);
close(fd);
return (file.st_size);
}
char *read_file(const char *filename)
{
char *content;
int file_size;
int fd;
ssize_t retval;
if ((file_size = ft_get_file_size(filename)) <= 0)
return (NULL);
content = (char *)malloc(sizeof(char) * file_size + 1);
fd = open(filename, O_RDONLY);
retval = read(fd, content, file_size);
content[retval + 1] = '\0';
close(fd);
return (content);
}
void write_file(char *file, char *content)
{
int fd;
fd = open(file, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR);
if (fd)
write(fd, content, strlen(content));
close(fd);
}
int main() {
char *test = read_file("ftp.en.pdf");
write_file("copy.pdf", test);
return EXIT_SUCCESS;
}
The process of downloading and uploading the file, is reading all the data from the file and then send that data to the socket. I have tried using mmap and I still get corrupted file.
Document is damaged error message
As binary data can have \0 characters, you cannot treat your content as a string, so strlen(content) is wrong. You must return the size of the content from your read_file function.
For example, define your function as char *read_file(const char *filename, int *size) and return the size in *size. Likewise define your write function as void write_file(char *file, char *content, int size)
(and forget the +1 in malloc)

How can I know text file is empty or not?(in C)

I'm trying to detect text file is empty or not in C.
(values are initialized in NULL)
Whenever read first in value(using fscanf), it always returns file has zero,
even if it has value "0" or "empty".
How can I know the target text file is empty or not?
(it should be distinguished even it has "0" in first letter)
If the file was successfully open for read, as per fopen(filename, "r"), you can verify if it is empty before any read operation this way:
int is_empty_file(FILE *fp) {
int c = getc(fp);
if (c == EOF)
return 1;
ungetc(c, fp);
return 0;
}
ungetc() is guaranteed to work for at least one character. The above function will return 1 if the file is empty or if it cannot be read, due to an I/O error. You can tell which by testing ferr(fp) or feof(fp).
If the file is a stream associated to a device or a terminal, the test code will block until at least one byte can be read, or end of file is signaled.
If the file is a regular file, you could also use a system specific API to determine the file size, such as stat, lstat, fstat (on Posix systems).
If you're under Linux, you can use stat or fstat:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);
Will give you this information:
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for file system I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
To check for the size using stat:
struct stat info;
if(stat(filepath, &info) < 0) {
/* error */
}
if(info.st_size == 0) {
/* file is empty */
}
Or using fstat:
int fd = open(filepath, O_RDONLY);
struct stat info;
if(fstat(fd, &info) < 0) {
/* error */
}
if(info.st_size == 0) {
/* file is empty */
}
you can do using ftell
#include <stdio.h>
int get_file_size (char *filename) {
FILE *fp;
int len;
fp = fopen(filename, "r");
if( fp == NULL ) {
perror ("Error opening file");
return(-1);
}
fseek(fp, 0, SEEK_END);
len = ftell(fp);
fclose(fp);
return(len);
}

mmap is wiping my file instead of copying it

So I'm using mmap to then write to another file. But the weird thing is, when my code hits mmap, what it does is clears the file. So I have a file that's populated with random characters (AB, HAA, JAK, etc...). What it's supposed to do is use mmap as read basically and then write that file to the new file. So that first if (argc == 3) is the normal read and write, the second if (argc ==4) is supposed to use mmap. Does anyone have any idea why on Earth this is happening?
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/io.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <sys/resource.h>
int main(int argc, char const *argv[])
{
int nbyte = 512;
char buffer[nbyte];
unsigned char *f;
int bytesRead = 0;
int size;
int totalBuffer;
struct stat s;
const char * file_name = argv[1];
int fd = open (argv[1], O_RDONLY);
int i = 0;
char c;
int fileInput = open(argv[1], O_RDONLY);
int fileOutPut = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
fstat(fileInput, &s);
size = s.st_size;
printf("%d\n", size);
if (argc == 3)
{
printf("size: %d\n", size);
printf("nbyte: %d\n", nbyte);
while (size - bytesRead >= nbyte)
{
read(fileInput, buffer, nbyte);
bytesRead += nbyte;
write(fileOutPut, buffer, nbyte);
}
read(fileInput, buffer, size - bytesRead);
write(fileOutPut, buffer, size - bytesRead);
}
else if (argc == 4)
{
int i = 0;
printf("4 arg\n");
f = (char *) mmap (0, size, PROT_READ, MAP_PRIVATE, fileInput, 0);
/* This is where it is being wipped */
}
close(fileInput);
close(fileOutPut);
int who = RUSAGE_SELF;
struct rusage usage;
int ret;
/* Get the status of the file and print some. Easy to do what "ls" does with fstat system call... */
int status = fstat (fd, & s);
printf("File Size: %d bytes\n",s.st_size);
printf("Number of Links: %d\n",s.st_nlink);
return 0;
}
EDIT: I wanted to mention that the first read and write works perfectly, it is only when you try to do it through the mmap.
If you mean it's clearing your destination file, then yes, that's exactly what your code will do.
It opens the destination with truncation and then, in your argc==4 section, you map the input file but do absolutely nothing to transfer the data to the output file.
You'll need a while loop of some description, similar to the one in the argc==3 case, but which writes the bytes in mapped memory to the fileOutput descriptor.

Resources