Low-Level I/O and Incremental Read/Write
#include <stdio.h>      /******  open1.c  ******/
#include <sys/stat.h>
#include <fcntl.h>
main()
{
  int fd;

  fd = open("junk", O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  write(fd, "hello\n", 6);
  close(fd);
}
/******************************************************************************/
$ open1
$ ls -l junk
-rw-------    1 jwp2286  staff          6 Jan 31 17:02 junk /* What's wrong? */
/******************************************************************************/

#include <sys/types.h>    /*****  open2.c  *****/
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
  int fd;

  umask(0);
  fd = open("junk", O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
  write(fd, "hello\n", 6);
  close(fd);
}
/******************************************************************************/
$ open2
$ ls -l junk
-rw-r--r--    1 jwp2286  staff          6 Jan 31 17:02 junk  /* O.K. now!! */
/*****************************************************************************/
File permissions:   S_IRUSR      Read for file owner.
                    S_IWUSR      Write for file owner.
                    S_IXUSR      Execute for file owner.
                    S_IRGRP      Read for group.
                    S_IWGRP      Write for group.
                    S_IXGRP      Execute for group.
                    S_IROTH      Read for others.
                    S_IWOTH      Write for others.
                    S_IXOTH      Execute for others.

Open modes:  O_RDONLY    Like fopen's "r" mode.
             O_WRONLY    Like fopen's "w" mode.
             O_RDWR      If file exists, it's like fopen's "r+" mode.
                         If file doesn't exist, it's like fopen's "w+" mode.
             O_CREAT     Create the file if it does not exist.  Requires that
                         open have a third argument -- file permissions.
             O_APPEND    Append to the end of the file on every write.
             O_TRUNC     Truncate file to zero length upon opening.

Example open:  open("foo.bar", O_CREAT | O_WRONLY | O_APPEND, S_IRUSR);

               Opens file like fopen's "a" mode.

#include <sys/types.h>    /**************  chmod demo  #1  *****************/
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
main()
{
   chmod("junk", S_IRWXU);
}
/*****************************************************************************/

$ ls -l junk
-rwxr-xr-x    1 jwp2286  staff          6 Jan 31 17:02 junk

$ chmod1
$ ls -l junk
-rwx------    1 jwp2286  staff          6 Jan 31 17:02 junk

#include <sys/types.h>   /**********  chmod demo #2   ************/
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
main()
{
   struct stat status;

   stat("junk", &status);
   chmod("junk", (status.st_mode & ~S_IRGRP) | S_IXOTH);
}
/*****************************************************************************/

$ chmod2
$ ls -l junk
-rwx-----x    1 jwp2286  staff          6 Jan 31 17:02 junk
/*****************************************************************************/

#include <fcntl.h>       /****  stat and fstat demo  ****/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <time.h>
main()
{
  int status, fd;
  struct stat fs;

  if ((fd = open("foo", O_RDONLY )) < 0)
  {
       printf("Open error on foo!\n");
       exit(1);
  }
  
  if ( (status = fstat(fd, &fs)) < 0)  /**  Stat is for closed files  **/
  {
       printf("Status error! Status = %d\n", status);
       exit(1);
  }

  /****
   ****  Status info. printed below.
   ****/

  printf("Inode = %ld\nLinks = %ld\n", fs.st_ino, fs.st_nlink);
  printf("Owner uid = %ld\nOwner gid  = %ld\n", fs.st_uid, fs.st_gid);
  printf("File size = %ld\n", fs.st_size);
  printf("Last modification = %ld mins. ago\n", (time(NULL) - fs.st_mtime)/60); 

  if (S_ISREG(fs.st_mode))  /****  S_ISDIR is also used frequently. ****/
  {
       if ( fs.st_mode & S_IRUSR) printf("User can read!\n");
       if ( fs.st_mode & S_IWUSR) printf("User can write!\n");
       if ( fs.st_mode & S_IXUSR) printf("User can execute!\n");
   /******
    ******  See Lewine page 539 for all st_mode values.
    ******/
  }
}             
/***************************  Program Output Below  **************************/

Inode = 43097
Links = 1
Owner uid = 2286
Owner gid  = 24
File size = 22
Last modification = 21 mins. ago   /***** 'Cause I just made it!  *****/
User can read!
User can write!

/************************  ls -il of the foo file  ****************************/

43097 -rw-------    1 jwp2286  staff         22 Oct  5 23:23 foo




#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
main()
{
  char buf[256];
  int count = 0, fd;

  while ( read(STDIN_FILENO, buf, 80))
  {  
     count++;
     printf("Cycle %d\n", count);
     write(STDOUT_FILENO, buf,80);
  }
  fd = open("foo", O_RDONLY);
  count = 0;
  while ( read(fd, buf, 80))
  {
     count++;
     printf("Cycle %d\n", count);
     write(STDOUT_FILENO, buf, 80);
  }
}
/**************************  SAMPLE EXECUTION *******************************/

abcd
Cycle 1    /* Input from terminal is still line buffered. */
abcd
efgh
Cycle 2
efgh
Cycle 1   /* Input from file is not!! */
abcdefg
hijklmn

/******************** CONTENTS OF FILE FOO ******************************/


abcdefg
hijklmn
#include <unistd.h>  /********  Blocking Versus Nonblocking Read  ********/
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>
#include <fcntl.h>

sigjmp_buf env;
int flags;

main()
{
     char buf[256] = "ARG!", outbuf[256];
     void handler(void);
     struct sigaction sa;
   
     sigfillset(&sa.sa_mask);
     sa.sa_handler = handler;
     sa.sa_flags   = 0; 
     sigaction(SIGALRM, &sa, NULL);
     alarm(10);

     printf("Enter stuff followed by CR: ");
     if (sigsetjmp(env, 1) == 0) printf("First time through!\n");
     else printf("Second time through!\n");

     read(STDIN_FILENO, buf, 80);
     sprintf(outbuf, "User typed: %s\n", buf);
     write(STDOUT_FILENO, outbuf, 90);
}



void handler(void)
{
      printf("I got here because time expired!!\n");
      alarm(0);

      flags = fcntl(STDIN_FILENO, F_GETFL, 0); /***** Get flags for stdin ****/
      flags |= O_NONBLOCK;   /*****  Set O_NONBLOCK bit in flags   *****/
      fcntl(STDIN_FILENO, F_SETFL, flags);  /***  Activate nonblocking read ***/
      sleep(3);
      siglongjmp(env, 5);
}
/*********************  SEVERAL EXAMPLE EXECUTIONS  ************************/

$ a.out
Enter stuff followed by CR: First time through!
I got here because time expired!!
Second time through!
User typed: ARG!  /* No he didn't!! Read fell through because I made it
                     non-blocking AND because I typed nothing during sleep!*/

$ a.out
Enter stuff followed by CR: First time through!
hello
User typed: hello    /* Alarm never invoked!  Stuff entered in < 10 secs. */

$ a.out
Enter stuff followed by CR: First time through!
I got here because time expired!!
hello
Second time through!
User typed: hello    /*  Hello got typed in during sleep!! */

$ a.out
Enter stuff followed by CR: First time through!
h
User typed: h
G!                /*  A quiz!  What happened here?  What're the implications? */
/******************************************************************************/

#include <unistd.h>  /**********  Errno's associated with read.  *********/
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
int flags;

main()
{
     char buf[256] = "ARG!", outbuf[256];
     int count = 0, retval;
     void handler(void);
   
     signal(SIGINT, handler);
     flags = fcntl(STDIN_FILENO, F_GETFL, 0);
     flags |= O_NONBLOCK;
     fcntl(STDIN_FILENO, F_SETFL, flags);

     retval = read(STDIN_FILENO, buf, 80);
     if (errno == EWOULDBLOCK) printf("Nothing in terminal buffer!\n");
     printf("Read return value: %d\n", retval);
     sprintf(outbuf, "User typed: %s\n", buf);

     write(STDOUT_FILENO, outbuf, 90);
     flags = fcntl(STDIN_FILENO, F_GETFL, 0);
     flags &= ~O_NONBLOCK;
     fcntl(STDIN_FILENO, F_SETFL, flags);

     memset(buf, 0, 80);     /******  Always do this in read loops!!  ******/
     errno = 0;
     retval = read(STDIN_FILENO, buf, 80);
     printf("User typed: %s\n : Read return value: %d\n", buf, retval);  
}


void handler(void)
{
     if (errno == EINTR) printf("Read terminated by signal!\n");
     printf("In signal handler!\n");
     exit(1);
}
/*************************  Sample Program Executions  ***********************/

$ read3
Nothing in terminal buffer!
Read return value: -1
User typed: ARG!
hello
User typed: hello

 : Read return value: 6

$ read3
Nothing in terminal buffer!
Read return value: -1
User typed: ARG!
User typed:    /* I hit a CTRL-D (Unix EOF) here! */
 : Read return value: 0

$ read3
Nothing in terminal buffer!
Read return value: -1
User typed: ARG!
/* I hit CTRL-C here to interrupt second read! */
In signal handler!   /* Notice that errno is NOT set to EINTR! */
                     /* This is an operating system bug! */
/******************  Incremental Read/Write Code   ***********************/
/******************  Works on fixed-length packets.***********************/

#include <stdio.h>

int readn(int fd, char *buf, int bytes)
{
     int nleft;
     int nread;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nread = read(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         else if (nread == 0)
              break;      /****  EOF!   ****/
         nleft -= nread;
         mover += nread;
     }
     return (bytes - nleft);
}


int writen(int fd, char *buf, int bytes)
{
     int nleft;
     int nwritten;
     char *mover = buf;

     nleft = bytes;
     while (nleft > 0){
         if ((nwritten = read(fd,mover,nleft)) < 0)
              return -1;  /**** Error!! ****/
         nleft -= nwritten;
         mover += nwritten;
     }
     return bytes;
}