Page 1 of 1

Unix utilities (rewriting cp)

Posted: Thu Dec 08, 2011 1:06 pm
by ajtgarber
I've decided to start rewriting Unix utilities using Unix library calls in C so that I can become more familiar with the library calls and C, and I've run into a bit of a snag. I've rewritten cp so that it actually copies the file, but when I try to use cat to see the contents of the file it always tells me that it doesn't have permissions. How can I transfer the permissions of the first file into the destination file? Right now I have it (hopefully) changing the user and group of the destination file to be the same as the user who ran my cp clone (the group that is copied is probably just the group that my clone is in).

Code:

Code: Select all

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
	if(argc < 2) {
		printf("Usage: %s <from> <to>\n", argv[0]);
		return 1;
	}
	int sourcefd = open(argv[1], O_RDONLY);
	int destinationfd = open(argv[2], O_WRONLY | O_CREAT);
	if(sourcefd == -1 || destinationfd == -1) {
		printf("Cannot open a file, dumping descriptors:\n");
		printf("sourcefd: %i\n", sourcefd);
		printf("destinationfd: %i\n", destinationfd);
		return 1;
	}
	int chownVal = fchown(destinationfd, (uid_t)getuid(), (gid_t)getgid());
	if(chownVal == -1) {
		printf("Unable to chown to current user :(\n");
	}

	char* buffer = (char*) malloc(sizeof(char*) * 1024); //make a 1KB buffer
	int numRead;
	while( (numRead = read(sourcefd, buffer, 1024)) > 0) {
		write(destinationfd, buffer, numRead);
	}

	//clean up
	close(sourcefd);
	close(destinationfd);
	free(buffer);

	return 0;
}
Permissions of copied file: (ls -l)
--wx--x--T 1 ajtgarber ajtgarber 911 Dec 8 14:05 copied.c
Another thing that confuses me is that the copied file has the executable flag set, even though its just a .c file and I don't
think I told it to give the new file that permission

Re: Unix utilities (rewriting cp)

Posted: Thu Dec 08, 2011 2:35 pm
by ajtgarber
I found how to do it, posting so people can possibly find this in the future:

Using the stat call I got a stat structure about the input file, then I passed the st_mode value from the structure
into the chmod cal.

Code:

Code: Select all

struct stat st;
int statVal = fstat(sourcefd, &st);
if(statVal == -1) {
	printf("Unable to stat %s\n", argv[1]);
}
int chmodVal = fchmod(destinationfd, st.st_mode);
if(chmodVal == -1) {
	printf("Unable to chmod %s\n", argv[2]);
}
Gotta love the man pages :P
man -s 2 stat