Question

this is for an assignment (not mine, but someone I'm helping, if that matters), but were supposed to write a program that mimics the unix ar command. I am very close to writing the file info to the header, using the stat() function, but I'm getting @^ instead of spaces when writing to the file.

here is an example of output

1-s.txt2^@^@^@^@^@^@^@^@Wed Oct 30 149972^@14601^@100640^@^@101^@^@^@^@^@^@^@ and it should be 1-s.txt2/ Wed Oct 30 149972 14601 100640 101

except the date should be a unix timestamp, any help with that would also be appreciated.

Thanks!!!

struct ar_hdr headerstruct;

void setfileinfo(const struct stat *sfileinfo){

sprintf(headerstruct.ar_name, "%s", global_argv[3]);

sprintf(headerstruct.ar_date, "%s", ctime(&sfileinfo->st_mtime));

sprintf(headerstruct.ar_uid, "%ld", (long)sfileinfo->st_uid);

sprintf(headerstruct.ar_gid, "%ld", (long) sfileinfo->st_gid);

sprintf(headerstruct.ar_mode, "%lo",(unsigned long)sfileinfo->st_mode);

sprintf(headerstruct.ar_size, "%lld",(long long)sfileinfo->st_size);

char filemag[2] = "`\n";

int fd;
fd = open(global_argv[2], O_RDWR);
lseek(fd, 0, SEEK_END);
write(fd, headerstruct.ar_name, 16);
write(fd, headerstruct.ar_date, 12);
write(fd, headerstruct.ar_uid, 6);
write(fd, headerstruct.ar_gid, 6);
write(fd, headerstruct.ar_mode, 8);
write(fd, headerstruct.ar_size, 10);
write(fd, filemag ,2);

return;

}
Was it helpful?

Solution

Since the ar header requires space padding, you might consider using memset to prefill the data structure or specific members with spaces. For example:

    memset(&headerstruct, ' ', sizeof(headerstruct));

Additionally, if you want to avoid null-terminated strings in the header, you should use something like memcpy or strncpy (with an appropriate length) instead of sprintf, as sprintf will insert a zero byte at the end of the string.

OTHER TIPS

You're writing a bunch of garbage because you're writing 16 (or whatever) characters no matter how long the strings are.

Try changing to this:

write(fd, headerstruct.ar_name, strlen(headerstruct.ar_name));

and so on. In the case where it is a fixed-length field, subtract 1 from your lengths, and deliberately write() a space character if you want that as a separator.

You're not getting @^, but ^@, which is a nul byte. That is, memory from the global variable headerstruct that is initialized to zero.

I would just use fprintf(3) instead of sprintf(3). The intermediate storage in a struct gives you no extra benefit.

If you want unused characters in those character arrays to be blanks, you need to put blanks there.

One way is something like

size_t ansize;

ansize = sizeof(headerstruct.ar_name);
snprintf(headerstruct.ar_name, ansize, "%-*.*s", (int)ansize, (int)ansize, global_argv[3]);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top