CS360 LAB ASSIGNMENT #1

                  CS360 LAB ASSIGNMENT #1
              DUE & DEMO: Thursday, 1-19-2023
		  
     1. Submit a ZIP file of YOUR code and outputs to TA BEFORE DEMO time
     2. Demo YOUR work to TA; TA will post demo schedule

=========================== Part 1 ======================================

		  PART 1: myprintf Function
		   
            Objective: I/O Function and Stack Usage

Given: putchar(char c) of Linux, which prints a char.

1-1. Write YOUR own prints(char *s) fucntion to print a string.
     If you don't know how to do it, you BETTER attend my class lecture !!!!

Given: The following printu() function print unsigned integer.

typedef unsigned int u32;

char *ctable = "0123456789ABCDEF";
int  BASE = 10; 

int rpu(u32 x)
{  
    char c;
    if (x){
       c = ctable[x % BASE];   
       rpu(x / BASE);
       putchar(c);           
    }
}

int printu(u32 x)
{
   (x==0)? putchar('0') : rpu(x);
   putchar(' ');
}

		          EXAMPLE:                             stack
      Assume u32 x = 123;                                      ------ High
      1st call to rpu(x): x=123; x%10 = 3 ===>  c = ctable[3] = '3';   
      2nd call to rpu(x): x=12;  x%10 = 2 ===>  c = ctable[2] = '2';  
      3rd call          : x=1;   x%10 = 1 ===>  c = ctable[1] = '1';  
      --------------------------------------------------------------- Low
      4th call          : x=0 => return  ====>      print       '1';
                                 retrun  ====>      print       '2'
                                 retrun  ====>      print       '3'

2-2. Write YOUR OWN fucntions
		  
 int  printx(u32 x) which print x in HEX   (prefixed with 0x )
 int  printd(int x) which print an integer (x may be negative!!!)


3. REQUIREMENTS:
====================================================================
   Write YOUR own myprintf(char *fmt, ...) function to print 
         char                      by %c
         string                    by %s
	 unsigned integer          by %u
		  
         unsigned integer in HEX   by %x
         integer                   by %d

   Ignore field width and precision, just print the items as specified.

1-3. In the int main(int argc, char *argv[ ], char *env[ ]) function, 
     use YOUR myprintf() to print
              argc value
              argv strings
              env  strings
    Then,
    myprintf("char=%c string=%s       dec=%u  hex=%x neg=%d\n", 
	        'A', "this is a test",  100,   100,   -100);

/********************** HELP INFO **************************/
NOTE: This assignment is for 32-bit GCC, which passes parameters on stack.
      Use  
               gcc -m32 t.c

      to compile your C source files.

int myprintf(char *fmt, ...)      // C compiler requires the 3 DOTs
{
   Assume the call is myprintf(fmt, a,b,c,d);
   Upon entry, the following diagram shows the stack contents.
 
                char *cp -> "...%c ..%s ..%u .. %d\n"
   HIGH               |                                              LOW 
 --------------------------- --|------------------------------------------
   | d | c | b | a | fmt |retPC| ebp | locals
 ----------------|----------------|---------------------------------------
                 |                | 
            int *ip            CPU.ebp
  
     1. Let char *cp point at the format string: HOW?

     2. Let int *ip  point at the first item to be printed on stack: HOW?

NOTE: In 32-bit mode, Every entry in the stack is 4-byte;
      for chars, they are in the lowest byte (of the 4-byte entry)
      for strings, they are POINTERs to the actual strings.
     
  *************** ALGORITHM ****************
   Use cp to scan the format string:
       spit out each char that's NOT %
       for each \n, spit out an extra \r

   Upon seeing a %: get next char, which must be one of 'c','s','u','x','d'
   Then call YOUR

        putchar(*ip) for 'c';
        prints(*ip)  for 's';
        printu(*ip)  for 'u';

        printx(*ip)  for 'x';
        printd(*ip)  for 'd';

   Advance ip to point to the next item on stack.

After implementing your myprintf() function, write C program to test your 
myprintf() function first. Then use it in the assignment.

SAMPLE Solution: ~samples/LAB1/myprintf   # download and run it

===================== Part 2 ============================================
								      
PART 2: Partition Table (This part is for general GCC, but you may use -m32)

2-1. OBJECTIVES
     Partition table, fdisk, structures in C, open-read files in Unix/Linux

2-2 Partition Table:

A disk (floppy disk, hard disk, USB drive, SD cards, etc.) consists of 512-byte
sectors, which are counted linearly as sector 0,1,2,3,....
 
A disk is usually divided into several partitions. The partitions are recorded 
in a partition table at the beginning (the 0th sector) of the disk, called the 
Master Boot Record (MBR). Inside the MBR, the partition table begins at the
byte offset 0x1BE. The Partitin Table contains 4 entries, each 16 bytes long, 
defined in the following C structure.

typedef unsigned char  u8;
typedef unsigned short u16;
typedef unsigned int   u32;

struct partition {
	u8 drive;             // drive number FD=0, HD=0x80, etc.

	u8  head;             // starting head 
	u8  sector;           // starting sector
	u8  cylinder;         // starting cylinder

	u8  sys_type;         // partition type: NTFS, LINUX, etc.

	u8  end_head;         // end head 
	u8  end_sector;       // end sector
	u8  end_cylinder;     // end cylinder

	u32 start_sector;     // starting sector counting from 0 
	u32 nr_sectors;       // number of of sectors in partition
  };
		  
		  Disk layout
          S0   S1   S2    ......
         ------------------------------------------------------
         |MBR|    |    |                                      |  
         ------------------------------------------------------

          S0 = 512-byte Sector
         -------------------------------------------------
         |                                   P1 P2 P3 P4 |
         ------------------------------------|------------
         0                                 0x1BE

heads, sectors, cylinders are for old IDE disks. 
Newer HD, USB, SD use only  start_sector and nr_sectors.
===========================================================================
So you may ignore the head, sector, cylinder fields of the partition table.
===========================================================================
 
Each partition has a type, which indicates what kind of file system the 
partition MAY contain. Consult Linux's fdisk command to see the partition types.

If a partition is EXTEND type (type=5), the partition's area can be further 
divided into more partitions. The extended partitions forms a LINK-LIST as the 
following diagram shows. 
------------------------------------------------------------------------------
Assume P4 is EXT type:
int extStart = P4's start sector; 
extStart = localMBR  
           E1:P5 start_sector (r.e. localMBR)
           E2:next localMBR   (r.e. extStart)
	                      localMBR
                              E1:P6's start_sector (r.e. localMBR)
                              E2:next localMBR     (r.e. extStart),etc

extStart sector is a localMBR. Each localMBR has a partition table with only 2 
entries. The first entry defines the start sector and size of the extended 
partition. The second entry points to the next localMBR. start_sector of a 
partition is RE to its localMBR sector#. All the localMBR sector# are relative
to extStart. As usual, the link list ends with a 0.
-------------------------------------------------------------------------------

Since use fdisk on real hard disks is risky, we shall use a VIRTUAL disk for
this assignment. A virtual disk is just a file but its contents are exactly the
same as a REAL disk. Download the file ~cs360/samples/LAB1/vdisk to YOUR Linux. 
Then, run       fdisk vdisk 
                 'p' : to see the partition table
                 'q' : to quit fdisk

                      REQUIREMENTS

2-3. Write a C progrom to display the partition table of vdisk in
 
(1). Linux fdisk 'p' output form for the first 4 partitions (%40),

(2). including ALL the extend partitions (%60) <== YOU BETTER DO THIS !!!!.

/* sample code for Part 2 */      
#include <stdio.h>
#include <fcntl.h>

#include <sys/types.h>
#include <unistd.h>

struct partition {
   // SAME AS GIVEN ABOVE    
};

char *dev = "vdisk";
int fd;
    
// read a disk sector into char buf[512]
int read_sector(int fd, int sector, char *buf)
{
    lseek(fd, sector*512, SEEK_SET);  // lssek to byte sector*512
    read(fd, buf, 512);               // read 512 bytes into buf[ ]
}

int main()
{
  struct partition *p;
  char buf[512];

  fd = open(dev, O_RDONLY);   // open dev for READ
  // read(fd, buf, 512);         // read 512 bytes of fd into buf[ ] 
  read_sector(fd, 0, buf);    // read in MBR at sector 0    

    buf[ ] contains 512 bytes of MBR
    -------------------------------------------------
    |                                   P1 P2 P3 P4 |
    ------------------------------------|------------
    0                                 0x1BE

  Write C code to let p point at Partition 1 in buf[ ];  HOW?

  print P1's start_sector, nr_sectors, sys_type;        SHOULD BE EASY

  Write code to print all 4 partitions;                 HOW?


  // ASSUME P4 is EXTEND type:
  Let  int extStart = P4's start_sector;
  print extStart to see it;

int localMBR = extStart;
loop:
  read_sector(fd, localMBR, buf);

  // partition table of localMBR in buf[ ] has 2 entries: 
  print entry 1's start_sector, nr_sector;
  compute and print P5's begin, end, nr_sectors

  if (entry 2's start_sector != 0){
     compute and print next localMBR sector;
     continue loop;
  }
}

SAMPLE Solution: ~samples/LAB1/ptable
                  Download and run it on vdisk to see the outputs