Using lseek() prints out repeated characters - c

char x[3];
char buff, c;
x[0]='y';
int offset, i;
int fd;
fd = open("test1.txt", O_RDONLY);
if(fd==-1){ printf("Error on fopen."); exit(1); }
offset = lseek(fd, 1, SEEK_END);
printf("Size of file is: %d. \n", offset);
for(i=offset-1; i>=0; i--)
{
c = read(fd, &buff, 1);
printf("The character is: %c. \n", c);
}
close(fd);
Running this gives me.
Size of file is: 6.
The character is: .
The character is: .
The character is: .
The character is: .
The character is: .
The character is: .
The test file contains only the word "TEST". I want to be able to print the word backwards.

read reads at the current position, and moves the current position forward by the amount read.
There needs to be further seeks. Also lseek( ..., 1, SEEK_END); probably ought to be lseek(...,0, SEEK_END); I would be uncomfortable with seeking to beyond the file.
for( i = ... ) {
lseek(fd, size - i, SEEK_BEGIN );
read(...);
}

Use fstat() to get the file size, as lseek() to SEEK_END is not guaranteed to return the size of a file, and you can use pread() to read a file in reverse without having to do any seeking at all. This is without any error checking - which should be added to any code that's going to be used:
struct stat sb;
int fd = open("test1.txt", O_RDONLY);
fstat( fd, &sb );
while ( sb.st_size > 0 )
{
char buff;
sb.st_size--;
pread( fd, &buff, sizeof( buff ), sb.st_size );
printf( "Char read: %c\n", buff );
}
close( fd );

Related

Why isn't lseek changing value? (C)

unsigned int file = open(argv[1], O_RDONLY);
printf("%u\n", file);
printf("%u\n", elf.offset);
lseek(file, elf.offset, SEEK_SET);
printf("%u", file);
OutPut:
3
52
3
Shouldn't file be set to 52?
Upon successful completion, the resulting offset, as measured in bytes from the beginning of the file, shall be returned.
try this printf("lseek_offset: %d\n", lseek(file, elf.offset, SEEK_SET));
file is a file descriptor. When you print it, you print the file descriptor, not the offset. When you lseek it to an offset of 52, the file descriptor is still 3, so it still prints 3.
You can read more about file descriptors here.
yon confuse file with file decriptor. The latter is just a non-negative integer that identifies an open file.
maybe this example can help you to understand these two concepts better:
char buf[8];
int main(){
int fd = open("test", O_RDONLY);
off_t offset = lseek(fd, 0, SEEK_CUR);
read(fd, buf, sizeof buf);
printf("first read when offset = %d : %s\n", (int)offset, buf);
offset = lseek(fd, 32, SEEK_SET);
read(fd, buf, sizeof buf);
printf("second read when offset = %d : %s\n", (int)offset, buf);
return 0;
}
and the output is:
first read when offset = 0 : 0000000
second read when offset = 32 : 4444444
here are the contents of test:
0000000\n
1111111\n
2222222\n
3333333\n
4444444\n

How to minimize the number of system calls? in C

How to minimize the number of system calls read() and write() in my code ?
int copy(char* entry, char* exit){
char buf;
int in;
int out;
in = open(entry,O_RDONLY);
out = open(exit ,O_APPEND|O_WRONLY);
while(read(in, &buf, 1) != 0){
write(out, &buf, 1); }
close(in);
close(out);
return 0;
}
Assuming you enlarge your buffer to for example 256, now write:
char buf[256];
int n;
...
while((n=read(in, buf, sizeof(buf))) > 0){
write(out, buf, n);
}
This reads, upon every read, a maximum of 256 bytes. read returns the number of bytes read, so n now has this number, which is what you write out. The last read will be less than 256, so the last write will also be less than 256.

pread returns 0 when it's not supposed to?

I am writing a file transfer program. However for some reason pread is returning 0 despite not being at the end of the file. Can anyone take a look at my code and see the problem? It works perfectly with fread.
int file;
unsigned int size = selfp->intdata;
file=open(str, O_RDONLY);
char buf[1024];
printf("filename = %s \n", str);//prints file name requested
printf("buffer = %s \n", buf);//prints nothing currently
printf("offset = %d \n",atoi(chunkIndex)*CHUNK);//prints 0 for first chunk
printf("CHUNK = %d \n", CHUNK);//prints 1024
int myoffset = atoi(chunkIndex)*CHUNK;
int dataSize=pread(file, buf, sizeof buf, myoffset);
printf("%d\n", dataSize);//returns 0
close(file);
Thanks!

c copy files in reverse order using lseek

I've got how to copy one file to another from start, but how could i modify the programme to copy it in reverse order? Source file should have read access and destination file read write execute. I have to use file control libraries.
for example
FILE A File B should be
|---------| |----------|
|ABCDEF | |FEDCBA |
|---------| |----------|
*********************UPDATE**********
Thank you, MikeNakis for hints and suggestions
,Sangeeth for your code
I've reworked the code and now it is copy bytes in reverse order printing filesize
here is the code
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<sys/stat.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
int source, dest, n;
char buf;
int filesize;
int i;
if (argc != 3) {
fprintf(stderr, "usage %s <source> <dest>", argv[0]);
exit(-1);
}
if ((source = open(argv[1], 0400)) < 0) { //read permission for user on source
fprintf(stderr, "can't open source");
exit(-1);
}
if ((dest = creat(argv[2], 0700)) < 0) { //rwx permission for user on dest
fprintf(stderr, "can't create dest");
exit(-1);
}
filesize = lseek(source, (off_t) 0, SEEK_END); //filesize is lastby +offset
printf("Source file size is %d\n", filesize);
for (i = filesize - 1; i >= 0; i--) { //read byte by byte from end
lseek(source, (off_t) i, SEEK_SET);
n = read(source, &buf, 1);
if (n != 1) {
fprintf(stderr, "can't read 1 byte");
exit(-1);
}
n = write(dest, &buf, 1);
if (n != 1) {
fprintf(stderr, "can't write 1 byte");
exit(-1);
}
}
write(STDOUT_FILENO, "DONE\n", 5);
close(source);
close(dest);
return 0;
}
You just seek to the end and start reading from there. No wonder it won't read anything. You need to seek to the end minus 1 byte, read one byte, write it, then seek to the end minus two bytes, read another byte, and so on.
I presume this is a homework assignment, so your professor should not mind the extreme inefficiency of this approach. (Real-world performance concerns are oh-so un-academic.) If he complains, tell him that in theory, it has the same time complexity as any other algorithm which would perform the same task: O(N). (That's pronounced "big oh of en".) He will give you an A+.
lseek(source, (off_t) i, SEEK_SET); should probably be lseek(source, (off_t) i - 1, SEEK_SET);

lseek() returning 0 when followed by new open()

I have the following bit of code (it's "example" code, so nothing fancy):
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
char buffer[9];
int fp = open("test.txt", O_RDONLY);
if (fp != -1) // If file opened successfully
{
off_t offset = lseek(fp, 2, SEEK_SET); // Seek from start of file
ssize_t count = read(fp, buffer, strlen(buffer));
if (count > 0) // No errors (-1) and at least one byte (not 0) was read
{
printf("Read test.txt %d characters from start: %s\n", offset, buffer);
}
close(fp);
}
int fp2 = open("test.txt", O_WRONLY);
if (fp2 != -1)
{
off_t offset = lseek(fp2, 2, SEEK_CUR); // Seek fraom current position (0) - same result as above in this case
ssize_t count = write(fp2, buffer, strlen(buffer));
if (count == strlen(buffer)) // We successfully wrote all the bytes
{
printf("Wrote to test.txt %d characters from current (0): %s\n", offset, buffer);
}
close(fp2);
}
}
This code does not return the first printout (reading) as it is, and the second printout reads: "Wrote test.txt 0 characters from current (0): " indicating that it did not seek anywhere in the file and that buffer is empty.
The odd thing is, if I comment out everything from fp2 = open("test.txt", O_WRONLY);, the first printout returns what I expected. As soon as I include the second open statement (even with nothing else) it won't write it. Does it somehow re-order the open statements or something else?
The line
ssize_t count = read(fp, buffer, strlen(buffer));
is wrong, you're taking the strlen of an uninitialized buffer. You likely want the size of the buffer like so:
ssize_t count = read(fp, buffer, sizeof buffer);
You should make sure buffer really contain a nul terminated string as well when you print it as one.
if (fp != -1) // If file opened successfully
{
off_t offset = lseek(fp, 2, SEEK_SET); // Seek from start of file
ssize_t count = read(fp, buffer, sizeof buffer - 1);
if (count > 0) // No errors (-1) and at least one byte (not 0) was read
{
buffer[count] = 0;
Are you perfectly sure you are cleaning out the file every time you run?
As written, the first time you run this, you'll only see the second printout, and the second time you might see the first one.

Resources