Homework 1 04/05/2005 - -- Chris Mooney ....................... UNIX Systems Engineer Project DoD ........................ http://home.dod.net/ P.O. Box 7012 ...................... Tel: (207) 450-2332 Portland, ME 04112 ................. chris@dod.net My PGP Public Key Block can be found at: http://chris.dod.net/pgp-public-key.asc Fingerprint: E5C2 E88A CED4 02CB 9D3C 8316 1001 E946 B592 F11C - - -- 1: So the getchar() function can return and error. (i.e. -1) 2: /usr/include is where the typical system files are located. There are also other locations like /usr/local/include or the directory of some package that libraries may be located. 3: Header files may store defines, global variable definitions, structures, function prototypes, some other stuff, and the secret to life. =-) 4: The problem is an overflow that is so large it puts nothing in the high order bytes of the int. This means the bit that indicates negative is completely skipped over. I also tested this with a long and masked out any bits in the upper 4 bytes of the storage, and there was nothing there. This means the overflow is so large that the lower order bits are changed without any indication that the upper bits have been set. To fix the problem, and indeed to find a better solution, we can change the while() condition of val > prevZ_val to: while((val % base) == 0) This would fix the problem for 10; however, it is possible that there may be some other base for which val overflows and still falls on a good multiple of base. One could combine a few techniques (masking and the original check) along with the mod() above to reduce the changes of this problem happening for all bases. 5: The man page for stat states that the function definition is: int stat(const char *file_name, struct stat *buf); The first argument is the filename that the system call should work on. The second argument takes a structure that will be filled with the meta-information of the file. The man pages also state that the return value is: "On success, zero is returned. On error, -1 is returned, and errno is set appropriately." 6: The two attributes are different logically in that one determines if the file is a character stream, file, directory, etc., and the other determines who, owner, group, other, has access along with any special operational attributes of the file (i.e. SUID, SGID, sticky bit). The differences in storage is subtle. Both attributes can be discerned from the stat structure's st_mode member, where the lower order bits indicate the mode and the upper special attributes and the file type. As far as the actual file is concerned, on the disk each file is associates with some meta-information. I hope this answers the question. This is how I read it. 7: The most obvious difference between open() and fopen is that one is a sort of standard C API for accessing files, while the other is the operating system's system call to open some "chunk" of data on the disk. I have found the fopen() can be limiting. For example, when I need to seek to different position and perform heavy file operations I typically prefer the speed and functionality of open(). There are some other differences like the two take different arguments and are written differently, but I assume that is obvious. 8: See program 3. =-) Just kidding. One can use the stat() sys-call to fill a struct stat with the meta-info for the file. You can then use the st_size member of the stat structure to get the information. struct stat info; stat("foo", &info); printf("%d\n", info.st_size); Note: this returns the time in bytes. 9: The shell implements the 'cd' and other commands directly. This means it must perform a chdir() to put the PID in the correct directory. If it did not do the and one changed directory to foo and attempted and ls, how would ls know what directory to open? Yah Yah, environment variables, yuck!! 10: The command 'ln /usr/bin/foo bar' would make a hard link to foo, called bar, in the current directory. Also 'ln -s /usr/bin/foo bar' would make a symbolic link in the same directory. Basically the answer is 'ln' and 'ln -s' respectively. 11: The FILE type can be chased down on both Solaris and Linux; however, the Solaris machines tell very little information about the usage of the structure. The Linux machines, on the other hand, do give information that seems to share similarities to the utmplib.c from the book. In the book we have the variables: fd_utmp num_recs cur_rec Where in the header file (/usr/include/libio.h) on the Linux systems we have: char* _IO_read_ptr; /* Current read pointer */ char* _IO_read_end; /* End of get area. */ char* _IO_read_base; /* Start of putback+get area. */ One would assume that one of the members is used as the file descriptor in the Linux header, but I don't know which one is. This unknown FD would correspond to the fd_utmp variable in utmplib.c. On the other hand we can see that the cur_rec variable corresponds to _IO_read_ptr, and that, while the cur_rec is used as a sort of offset into the utmp file, the _IO_read_base and _IO_read_end could get you the same sort of information. 12: The actual length is dynamic; however, there is a trick in C which allows you to, allocating memory sequentially, put an array at the end of a structure and and still allow you to access its memory. The problem with using a char * is that once the memory is allocated, one must assign the pointer to the appropriate place in memory. This additional step makes the other solution better. 13: The link count for the directory means there are n number of hard links to that directory. The reason every directory has at least two is because the parent to that directory must contain the information for the dir in question, and the dir contains a reference to '.' for itself. The real question is, can someone boot a system, do an rm -fr on /* and change the link count? The /dev or /proc dir would probably stop this, but its a fun idea. 14: I better get credit for this because I accidentally removed file in my home directory. I did a 'mkdir foo', 'cd foo', 'rm -fr ../', and then when it took too long I hit CTRL-C. I have no idea what I removed in my home directory. But I hate this question. It is a good idea that rm does not remove dirs with files in it because it would remove all files and directories in that dir. In effect, rm would do a recessive remove on a directory if it were to perform this operation. As we can see from my mistake... that is bad. Here is the test from the book. What's more, of you do an ls you will get a stale NFS handle. greenlantern <19:25:58>% mkdir foo greenlantern <19:26:25>% cd foo/ greenlantern <19:26:27>% rm -fr ../foo/ greenlantern <19:26:30>% pwd pwd: cannot get current directory: No such file or directory greenlantern <19:26:33>% /bin/pwd /bin/pwd: cannot get current directory: No such file or directory 15: The permutations of AS AW BS BW that cause a race condition are: Time | R1 | R2 | R3 | R4 | ----------------------------------- 1 | BS | AS | BS | AS | 2 | AS | BS | AS | BS | 3 | AW | BW | BW | AW | 4 | BW | AW | AW | BW | ----------------------------------- Where Rn indicates the race condition for that sequence.