How to print mmap file content ? void * to char * - c

int fd = open(argv[1], O_RDONLY);
struct stat bf;
fstat(fd, &bf);
void *adr = mmap(NULL, bf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
for (size_t i = 0; i <= bf.st_size; i++)
{
printf("%c", adr[i]); // doesn't work invalid use of void expression
}
I'm trying to print the content a file, but I don't understand why I can't convert
to char*
printf("%c", (char*) adr[i]);

Related

copying with memcpy some data to mmap return pointer address location of a file

If I have a file which I mapped with mmap like this
sfd = open("test.txt", O_RDONLY);
filesize = lseek(sfd, 0, 10);
src = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, sfd, 0);
so right now the sizeof mapping is 0 bytes because size of test.txt is 0. So what if I want to write word hello to mapped area. How to do it?
I tried like this
memcpy(src,"hello", sizeof("hello"));
But this throws Bus error. I could use mremap but that is not available on my system. So I like to know how to write to mapped area something with memcpy
Update
This is my code and now it giving me segFault at memcpy line
int main(int argc, char **argv){
int sfd, dfd;
char *src, *dest;
size_t filesize=10;
/* SOURCE */
sfd = open("test.txt", O_RDWR);
src = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, sfd, 0);
ftruncate(sfd,10);
if(src== MAP_FAILED)
{printf("error\n");exit(0);}
/* DESTINATION */
memcpy(src,"hello", sizeof("hello"));
munmap(src, filesize);
close(sfd);
close(dfd);
return 0;
}

problem in a variant of copy command using mmap()

I have a program which is another variant of copy program in linux(Actually I'm on Mac OSX).
In order to support copying large files, I wrote something like this:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#define BUFFSIZE 65535
#define PAGESIZE 4096
int main(int argc, char **argv){
char *source, *destination;
int src_fd, dst_fd;
unsigned long long bytes_read;
int bytes = BUFFSIZE;
struct timeval start, end;
int overall_time = 0;
unsigned long long offset = 0;
struct stat statbuf;
if(argc < 3){
printf("copy <source> <destination>\n");
exit(EXIT_FAILURE);
}
source = argv[1];
destination = argv[2];
src_fd = open(source, O_RDONLY, 0777);
if(src_fd < 0){
perror("src_fd");
exit(EXIT_FAILURE);
}
//bytes_read = lseek(src_fd, 0, SEEK_END);
fstat(src_fd, &statbuf);
bytes_read = statbuf.st_size;
dst_fd = open(destination, O_RDWR | O_CREAT, 0777);
if(dst_fd < 0){
perror("dst_fd");
exit(EXIT_FAILURE);
}
lseek(dst_fd, bytes_read -1, SEEK_SET);
write(dst_fd, "", 1);
gettimeofday(&start, NULL);
while(bytes_read > 0){
if(bytes_read < BUFFSIZE){
bytes = bytes_read;
bytes_read = 0;
}
else{
bytes_read -= bytes;
}
void *src_map = mmap(NULL, bytes, PROT_READ, MAP_SHARED, src_fd, (off_t)offset);
if(src_map == (void*) MAP_FAILED){
perror("src_map");
exit(EXIT_FAILURE);
}
void *dst_map = mmap(NULL, bytes, PROT_WRITE, MAP_SHARED, dst_fd, (off_t)offset);
if(dst_map == (void*) MAP_FAILED){
perror("dst_map");
exit(EXIT_FAILURE);
}
memcpy(dst_map, src_map, bytes);
int src_unmp = munmap(src_map, bytes);
if(src_unmp == -1){
perror("src_unmap");
exit(EXIT_FAILURE);
}
int dst_unmp = munmap(dst_map, bytes);
if(dst_unmp == -1){
perror("dst_unmap");
exit(EXIT_FAILURE);
}
offset += 4096;
bytes_read -= bytes;
}
gettimeofday(&end, NULL);
printf("overall = %d\n", (end.tv_usec - start.tv_usec));
close(src_fd);
close(dst_fd);
return 0;
}
The goal is to measure the amount of time elapsed to copy a large file with the use of mmap().
The above code is not working for transferring 1GB file.
Any hint for that?
Thank you
Yes. The problem is in offset value. The offset value should be a multiple of page size.

mmap function for arrays of data

Suppose that you have a binary file. It consists of double's. Its size is enough small to be put in the memory. How to read all of these numbers by using mmap function?
I have tried to dereference output pointer. But it is only the first element of data. To use loop it's non-trivial how to control the quantity of the elements of the array.
int main(int argc, char* argv[]) { // we get filename as an argument from the command line
if (argc != 2)
return 1;
int fd = open(argv[1], O_RDWR, 0777);
size_t size = lseek(fd, 0, SEEK_END);
double m = 0;
int cnt = 0; // counter of doubles
void* mp = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (mp == MAP_FAILED)
return 1;
double* data = mp;
m += *data; // we want to count the sum of these doubles
++cnt;
int ump_res = munmap(mp, sizeof(double));
if (ump_res < sizeof(double))
return 1;
printf("%a\n", (m / (double)cnt)); // we output the average number of these doubles
close(fd);
return 0;
}
I expect that in stdout we will get the average of all doubles in the file, which name is give in argv[1] .
It is possible to cast void* to double* .Then you may iterate and handle elements:
void* mp = mmap(0, length, PROT_READ, MAP_PRIVATE, fd, 0);
if (mp == MAP_FAILED) {
close(fd);
return 1;
}
double* data = (double*)mp;
size_t cnt = length / sizeof(double);
for (size_t i = 0; i < cnt; ++i) {
m += data[i];
}
Hope you'll find it helpful.

C - little code, file descriptor, segmentation fault

I have write this code but i have a problem
first i have a function that create a file descriptor (fd)
int fd;//global
static int init_fd(int fd) {
remove("file descriptor.txt");//if yet present
fd = open("file descriptor.txt", O_WRONLY | O_CREAT, 0666);
if (fd == -1) {
printf("Error in opening the file descriptor!\n");
exit(0);
}
return fd;
}
the second function is a handler function
static int handler(struct connection *conn, enum event ev) {
...
int i;
for (i = 0; i < array_size; i++) {
if (!strncmp(conn->uri, uri_array[i], strlen(uri_array[i]))) {
func_array[i](conn->request_method, conn->uri, NULL, init_fd(fd));
close(fd);
fd = open("file descriptor.txt", O_RDONLY);
ret = read(fd, &buf, BUFSIZ);
if (ret == -1) {
printf("Error in reading!\n");
exit(0);
}
...
}
with fun_array is a pointer to function
httpCallback_t func_array[MAXARRAY];
and the function is
void http_serve1(const char *method, const char *path, const httpOptions_t *options, int fd) {
const char *string = "All is ok1!";
int ret_value;
// send header: 200 OK
ret_value = sendHeaders(fd, TIMEOUT_SEC, NETHTTP_HTTP_HEADER_200, NETHTTP_Content_Type_text_html_utf8, NETHTTP_CRLF, NULL);
// close the file descriptor
close(fd);
}
and the function sendHeaders is
size_t sendHeaders(int fd, int seconds, const char* header1, ...) {
va_list args;
va_start(args, header1);
size_t totalSize = 0;
const char* hdr = header1;
while (hdr != NULL) {
size_t result = sendHeaders(fd, seconds, hdr, NULL); // segmentation fault
if (result < 0) {
return result;
}
totalSize += result;
hdr = va_arg(args, const char*);
va_end(args);
return totalSize;
}
if (size == SIZE) {
setErrorCode(ERROR);
return ERROR;
}
size_t sizewrite = 1024;
tmp[size] = strdup(hdr);
write(fd, tmp, sizewrite);
setErrorCode(SUCCESS);
return SUCCESS;
}
my problem is that my code create a file descriptor, but it doesn't write inside, and during the run i have problem with segmentation fault. anyone have a suggest?

Better Way To Read From An exec'd Program's stdout in C

I read an exec'd program's stdout using a pipe:
int pipes[2];
pipe(pipes);
if (fork() == 0) {
dup2(pipes[1], 1);
close(pipes[1]);
execlp("some_prog", "");
} else {
char* buf = auto_read(pipes[0]);
}
To read from stdout, I have a function auto_read which automatically allocates more memory as needed.
char* auto_read(int fp) {
int bytes = 1000;
char* buf = (char*)malloc(bytes+1);
int bytes_read = read(fp, buf, bytes);
int total_reads = 1;
while (bytes_read != 0) {
realloc(buf, total_reads * bytes + 1);
bytes_read = read(fp, buf + total_reads * bytes, bytes);
total_reads++;
}
buf[(total_reads - 1) * bytes + bytes_read] = 0;
return buf;
}
The reason I do it this way is I don't know how much text the program is going to spew out ahead of time, and I don't want to create an overly large buffer and be a memory hog. I'm wondering if there is:
A cleaner way to write this.
A more memory or speed-efficient way of doing this.
Use popen if you only need to read from a process and are on a *NIX platform:
FILE *programStdout = popen("command", "r");
// read from programStdout (fread(), fgets(), etc.)
char buffer[1024];
while (fgets(buffer, 1024, programStdout))
{
puts(buffer);
}
EDIT: You asked for a way to map a programs output to a file, so here you go:
#import <stdio.h>
#import <unistd.h>
#import <sys/mman.h>
void *dataWithContentsOfMappedProgram(const char *command, size_t *len)
{
// read the data
char template[] = "/tmp/tmpfile_XXXXXX";
int fd = mkstemp(template);
FILE *output = fdopen(fd, "w+");
FILE *input = popen(command, "r");
#define BUF_SIZ 1024
char buffer[BUF_SIZ];
size_t readSize = 0;
while ((readSize = fread(buffer, 1, BUF_SIZ, input)))
{
fwrite(buffer, 1, readSize, output);
}
fclose(input);
input = NULL;
#undef BUF_SIZ
// now we map the file
long fileLength = ftell(output);
fseek(output, 0, SEEK_SET);
void *data = mmap(NULL, fileLength, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, 0);
close(fd);
if (data == MAP_FAILED)
return NULL;
return data;
}
int main()
{
size_t fileLen = 0;
char *mapped = dataWithContentsOfMappedProgram("echo Hello World!", &fileLen);
puts(mapped);
munmap(mapped, fileLen);
}

Resources