I am fairly new to writing C code and I am sure I have something wrong at the very basic level. I am running a small code to get the attributes of a file and this function below returns those attributes.
char *path would contain something like “/home/etc/bin”
/* copy the attributes into a character pointer */
unsigned char * copyAttributes (char *path)
{
struct stat buf;
stat (path, &buf);
int nMalloc = sizeof(dev_t) + sizeof(ino_t) + sizeof(mode_t)+ sizeof(nlink_t)+ sizeof(uid_t)+ sizeof(gid_t)+ sizeof(dev_t)+ sizeof(off_t)+ sizeof(blksize_t)+ sizeof(blkcnt_t)+ sizeof(time_t)+ sizeof(time_t)+ sizeof(time_t)+ 1;
char *pathForStatBuff = malloc(nMalloc);
printf("%d\n",nMalloc);
unsigned long base = 0;
memcpy(pathForStatBuff + base,&buf.st_dev,sizeof(dev_t));
base = base + sizeof(dev_t);
memcpy(pathForStatBuff + base,&buf.st_ino,sizeof(ino_t));
base = base + sizeof(ino_t);
memcpy(pathForStatBuff + base,&buf.st_mode,sizeof(mode_t));
base = base + sizeof(mode_t);
memcpy(pathForStatBuff + base,&buf.st_nlink,sizeof(nlink_t));
base = base + sizeof(nlink_t);
memcpy(pathForStatBuff + base,&buf.st_uid,sizeof(uid_t));
base = base + sizeof(uid_t);
memcpy(pathForStatBuff + base,&buf.st_gid,sizeof(gid_t));
base = base + sizeof(gid_t);
memcpy(pathForStatBuff + base,&buf.st_rdev,sizeof(dev_t));
base = base + sizeof(dev_t);
memcpy(pathForStatBuff + base,&buf.st_size,sizeof(off_t));
base = base + sizeof(off_t);
memcpy(pathForStatBuff + base,&buf.st_blksize,sizeof(blksize_t));
base = base + sizeof(blksize_t);
memcpy(pathForStatBuff + base,&buf.st_blocks,sizeof(blkcnt_t));
base = base + sizeof(blkcnt_t);
memcpy(pathForStatBuff + base,&buf.st_atime,sizeof(time_t));
base = base + sizeof(time_t);
memcpy(pathForStatBuff + base,&buf.st_mtime,sizeof(time_t));
base = base + sizeof(time_t);
memcpy(pathForStatBuff + base,&buf.st_ctime,sizeof(time_t));
base = base + sizeof(time_t);
printf("Printing pathForStatBuff = %s\n",pathForStatBuff);
return pathForStatBuff;
}
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
53
Printing pathForStatBuff = p
This is the output I always get, I can’t seem to figure out what I am doing wrong. Could you guys guide me on what it might be. Thanks.
At first sight, the code:
is doing exactly the same as
Edit: WARNING – caf pointed out that the
is not necessarily exactly the same as
int nMalloc = sizeof(struct stat);The fields within
struct statmight have alignment constraints which cause there to be ‘holes’ or padding in between fields. There might also be undocumented fields. So struct stat might be bigger than the sum of its published fields.This would be straightforward to check.
but might change in future, so your original is more robust.
Based on caf’s proposition, this is also not necessarily identical:
to:
memcpy(pathForStatBuff, &buf, sizeof(struct stat));but the size test would detect that.
So, field assignment to a new struct would allow you to get control of the fields needed, their order, and some aspects of layout (same compiler/same platform).
If memcpy is preferred, look at mempcpy. It is like memcpy, but returns a pointer to the byte after the last one, so you don’t need to do:
but instead have an extra pointer and do
Do you want to get a printable form? If that is the case, you will need to use sprintf, printf, or fprintf. As you are learning, I would convert all of the memcpy’s to
printf("..., buf....field ...);and see them immediately, that will be easier than getting a string right first time.