When chaos begin...
1. test dup and lseek:
Question: If you dup an open file with another file-descriptor, does it lseek operation affects the read-write of 
file descriptor which it dups from?
Answer: Of course, since they are actually pointing to the same file tables.
(Hint: You have to compile it with g++ instead of gcc in "sunset". Sucks!)
//#include	<sys/types.h>
#include 	<stdio.h>
#include        <stdlib.h>
#include	<string.h>
#include 	<unistd.h>
#include	<fcntl.h>
#include 	<errno.h>
#define  MaxBuf    20

int main(int argc, char *argv[])
{

	int fd1, fd2, n;
	char buf[MaxBuf+1];
	if (argc!=2)
	{
		printf("usage: file1.o file2\n");
		exit(errno);
	}
	if ((fd1=open(argv[1], O_RDONLY))==-1)
	{
		//perror(atoi(buf, fd1, 10));
		printf("open error\n");
	}

	fd2=dup(fd1);
	printf("%d read first %d\n", fd1,  MaxBuf);
	if ((n=read(fd1, buf, MaxBuf))==-1)
	{
		printf("file descriptor %d read error", fd1);
	}
	buf[n]='\0';
	printf("%d read this %s\n", fd1, buf);
	if ((n=read(fd1, buf, MaxBuf))==-1)
	{
		printf("file descriptor %d read error", fd1);
	}
	buf[n]='\0';
			

	printf("%d should read this line next %s\n", fd1, buf);
	printf("%d now seek back %d\n", fd1, n);
	if (lseek(fd1, -n, SEEK_CUR)==-1)
	{
		printf("%d seek back error\n", fd1);
	}
	printf(" %d seek to beginning again\n", fd2);

	if (lseek(fd2, 0, SEEK_SET)==-1)
	{
		printf("seek error of %d\n", fd2);
	}
	printf("%d begin to read again\n", fd1);

	if ((n=read(fd1, buf, MaxBuf))==-1)
	{
		printf("%d read error\n", fd1);
	}
	buf[n]='\0';
	printf("%d read this line %s\n", fd1, buf);
}
Result:
3 read first 20
3 read this //#include <sys/type
3 should read this line next s.h>
#include <stdi
3 now seek back 20
4 seek to beginning again
3 begin to read again
3 read this line //#include <sys/type
2. test dup and lseek:
Question: How do we implement "ls"? Actually this is just a re-do of my comp229 assignment. However, I just implement part of it.
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

const int MaxPathLength=128;
void dirView(char* dirName, char* pathName);
void errHandle(char* msg);
void myls();

int main(int argc, char* argv[])
{
	char fullPath[MaxPathLength];
	if (argc!=2)
	{
		printf("usage: dirview dirName\n");
		exit(1);
	}
	if (getcwd(fullPath, MaxPathLength)==NULL)
	{
		errHandle("getcwd error\n");
	}
	dirView(argv[1], fullPath);

	return 0;
}
	


void myls()
{
	char fullPath[MaxPathLength];
	if (getcwd(fullPath, MaxPathLength)==NULL)
	{
		errHandle("getcwd error\n");
	}
	dirView(".", fullPath);
}


void dirView(char* dirName, char* pathName)
{
	char fullPath[MaxPathLength];
	char fileName[MaxPathLength];
	DIR* dp;
	char* ptr;
	dirent* dirNode;
	struct stat statBuf;
	strcpy(fullPath, pathName);
	ptr=fullPath+strlen(fullPath);
	*ptr='/';
	ptr++;
	*ptr='\0';
	strcat(fullPath, dirName);
	if ((dp=opendir(fullPath))==NULL)
	{
		printf("fullpath=%s\n", fullPath);
		errHandle("error open directory\n");
	}
	printf("print directory of %s\n", fullPath);
	while ((dirNode=readdir(dp))!=NULL)
	{
		if (strcmp(dirNode->d_name, ".")==0
		|| strcmp(dirNode->d_name, "..")==0)
		{
			continue;
		}
		strcpy(fileName, fullPath);
		ptr=fileName+strlen(fileName);
		*ptr='/';
		ptr++;
		*ptr='\0';
		strcat(fileName, dirNode->d_name);
		if (lstat(fileName, &statBuf)<0)
		{
			printf("fileName=%s\n", fileName);
			errHandle("lstat error\n");
		}
		if (S_ISDIR(statBuf.st_mode))
		{
			//now fullPath is including the name
			dirView(dirNode->d_name, fullPath);
		}
		else
		{
			printf("regular file: %s\n", dirNode->d_name);
		}
	}
}
		
		
void errHandle(char* msg)
{
	perror(msg);
	exit(errno);
}
Result:
print directory of /nfs/home/q/qingz_hu/comp444/files/mytest/mydir
regular file: arena.cpp
regular file: arena.o
regular file: arena.txt
regular file: dirview.c
regular file: dirview.o
regular file: io.c
regular file: io.c~
regular file: io.out
regular file: myhead.h
regular file: myhead.h~
regular file: mylib.c
regular file: mylib.c~
regular file: mylib.h
regular file: ourhdr.h
regular file: result.txt
regular file: test.txt
regular file: test.txt~
print directory of /nfs/home/q/qingz_hu/comp444/files/mytest/mydir/mynewdir
regular file: dirview.c
regular file: io.c
regular file: mylib.c
 

3. copy files:
Question: Does a copy file system call exist in UNIX? Amazingly the answer is NO! And it is fairly straight-forward to do it.
The only difference between my implementation and standard "cp" is that I will generate an error if target file already exists.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>


const int MaxBufLength=1024;
const int MaxPathLength=128;
//const int MaxMsgLength=32;
void copyfile(char* fullPath, char* newPath);

void errHandle(char* msg); 

//char msg[MaxMsgLength];


int main(int argc, char* argv[])
{
	if (argc!=3)
	{
		errHandle("usage: copyfile source target");
	}
	
	copyfile(argv[1], argv[2]);
	return 0;
}


void errHandle(char* msg)
{
	perror(msg);
	exit(errno);
}



void copyfile(char* fullPath, char* newPath)
{
	int fdOld, fdNew, n;
	char buf[MaxBufLength];
	struct stat statBuf;
	if ((fdOld=open(fullPath, O_RDONLY))<0)
	{
		//perror("file not exists");
		//exit(errno);
		errHandle("file not exists");
	}
	if (lstat(fullPath, &statBuf)<0)
	{
		errHandle("stat error");
	}
		
	if ((fdNew=open(newPath, O_WRONLY|O_CREAT |O_EXCL, statBuf.st_mode))==-1)
	{
		errHandle("creat error or file already exists");
	}
	  
	while ((n=read(fdOld, buf, MaxBufLength))!=0)
	{
		if (n<0)
		{
			errHandle("read old file error");
		}
		if (write(fdNew, buf, n)!=n)
		{
			errHandle("write new file error");
		}
	}
	if (close(fdOld)<0)
	{
		errHandle("cannot close old file");
	}
	if (close(fdNew)<0)
	{
		errHandle("cannot close new file");
	}
}
	
Result: Originally I worried a lot about the path of both source and target file because I am not sure if I need
require user to give full path name of both source and target because it would be inconvenient to ask user to copy
some file in current working directory and give the long path name. After testing I was relieved since "lstat" is
NOT a basic system call and it can do a simple parsing job to see if the file name is relative or absolute. This 
is something I discovered unexpectedly.
To run, just type ./copyfile.o source target
 
4. binary formats:
Question: I suspect that the UNIX programmers are either lazy or arrogant because they even didn't bother to implement a simple 
format of "printf()" which print the binary format of an integer. I use it quite often on windows version of "printf()" and 
logically assume it is also implemented in UNIX. It is not. So, I just practice by writing a simple one. The only reason I mention
this simple code is that the problem of signed and unsigned integer. It takes me nearly one hour to figure out the problem is 
the "atoi" only return signed integer. Therefore in argument to "main" from command line, I cannot pass the biggest unsigned 
integer  4294967295. Before find this, I nearly begin suspect my memory about 2's complement. And indeed my memory  is as bad as
that. You see, I even call this "Euclid algorithm". What a joke? It is not GCD problem! Sigh... My memory!
 
#include <stdlib.h>
#include <stdio.h>

void binary(unsigned int number, char* buf);

int main(int argc, char* argv[])
{
	unsigned int num=4294967295;
	char* buf=(char*)malloc(sizeof(int)*8+1);
	if (argc==1)
	{
		printf("because atoi function will not work with unsigned int, I cannot input biggest int by argument\n");
		binary(num, buf);
		printf("So, I have to display the largest number:%d like this %s\n", num, buf);
		exit(0);
	}
	if (argc==2)
	{
		num=atoi(argv[1]);
		printf("%u\n", num);
		//one byte equals 8 bits and extral byte for NULL	
		binary(num, buf);
		printf("%s\n");
	}
	
	return 0;
}

void binary(unsigned int number, char* buf)
{
	unsigned int size=sizeof(int)*8;
	unsigned int quotion=number, modulo=0;
	buf[size]='\0';
	//euclid algorithm goes from end to beginning
	do
	{
		size--;
		modulo=quotion%2;
		quotion/=2;
		buf[size]='0'+modulo;
	}
	while (size>0);
}
	
 
 
 
This is the contents of running script file "test":
./printftest.o 12
./printftest.o 1024
./printftest.o 4294967295
./printftest.o
And I run it to redirect result to a result file:
[qingz_hu@alamanni ~/mywork] % chmod +x test
[qingz_hu@alamanni ~/mywork] % ./test >myresult.txt
Then you will see the running result as following:
(Please note that the biggest unsigned int 4294967295 is interpreted by "atoi" as a signed int as 2147483647 which is roughly half
of original one. I cannot find a unsigned version of "atoi". I cannot even find help by "man atoi". ????)
12
00000000000000000000000000001100
1024
00000000000000000000010000000000
2147483647
01111111111111111111111111111111
because atoi function will not work with unsigned int, I cannot input biggest int by argument
So, I have to display the largest number:-1 like this 11111111111111111111111111111111
	The strange behaviour of "readlink" 
In class professor showed us the strange behaviour of "readlink". But I cannot re-do it myself:
I feel very curious of the strange behaviour of "readlink" during demo. So, I tried to redo it myself as following:

Create a symbolic link and then read the contents of it. However, it seems that "readlink" behaves normally by returning the number of bytes it read. Since the source code is not posted, I wonder if I missed something:

#include "myhead.h"
//I don't like Steven's head file, so I define my own little one with included headers, constants
 
void myreadlink(char* pathName);

int main(int argc, char* argv[])
{
        //this little test first create a symbolic link and then read it
        if (argc!=3)
        {
                errHandle("usage: myreadlink.o targetPath, symlinkname\n");
        }
        if (symlink(argv[1], argv[2])<0)
        {
                errHandle("symlink error\n");
        }
        printf("now read symbolic link %s\n", argv[2]);
        myreadlink(argv[2]);
        return 0;
}
 
void myreadlink(char* pathName)
{
        char buf[BuffSize];
        int n;
        if ((n=readlink(pathName, buf, BuffSize))<0)
        {
                errHandle("readlink error\n");
        }
        buf[n]='\0';
        printf("%s is a softlink with contents of length of %d:%s\n", pathName,n, buf);
}
 

The running result is like this:

[qingz_hu@alamanni ~/mywork] % gcc myreadlink.c -o myreadlink.o

[qingz_hu@alamanni ~/mywork] % ./myreadlink.o ./nicktest mynewlink

now read symbolic link mynewlink

mynewlink is a softlink with contents of length of 10:./nicktest

[qingz_hu@alamanni ~/mywork] % 

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>
#include <unistd.h>

const int BuffSize=128;

void errHandle(char* msg);

void errHandle(char* msg)
{
        if (msg!=NULL)
        {
                perror(msg);
        }
        else
        {
                strerror(errno);
        }
        exit(errno);
}
 
 

                        back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)