C PROGRAMMING FILE IO

 Many examples come from either Beginning Linux Programming by Neil Matthew and Richard Stones Or from Dr. Robert Siegfried

Difference between Unix system file calls and stdio file stream buffered functions: (In this class, we explore unbuffered OPEN Unix System calls using the file descriptor and in 270 we explore FOPEN buffered stdio.h calls using a file pointer.)

 

FOPEN

OPEN

Source

Stdio.h

Unix system call

Comparison of features

Buffered

Not buffered

 

Handles interrupted writes on its own

Programmer has  to handle interrupted writes

 

Buffering can be faster

System calls can be slow

 

Does ascii line end translation

Does not translate any character including line end

 

 

Open is guaranteed to be supported on any unix system.

 

 

Permission control for creating new files

 

 

Frequently used for socket and device drivers because of non-blocking

Handle

File pointer to file descriptor structure

File Descriptor Number

Convert to Handle type

fdopen(give fd and get FILE *)

Fileno (give FILE * and get fd)

 

System tables involved in writing and reading files:

·         File descriptor table – 1 per process with one row per open file (0,1,2 are given as stdin, stdout and stderr) ; points to the open file table

·         Open file table – 1 per system with one per opener of a file; points to the inode table; holds current writing position

·         Inode table – 1 per physical file; points to the actual file location

Open file

·         int fd = open(pathname, flags, mode);

o   Use comma to separate the 3 parms, and use | to separate all the options you put into each parm.

·         examples:

o    int outp = open("file1.txt", O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWGRP)

§  // create file and error if it exists (due to O_EXCL) and allow Writing to the file.  The new file will ask for the permissions of read for the user and write for the group. However, if UMASK does not allow, you wont get the permission. You will see that in ls -l

o   int outp = open("file1.txt", O_APPEND | O_WRONLY)

§  // open file to append: You can never change the contents of the original file with that – only add to the end.

o   int outp = open("file1.txt",   O_WRONLY)

§  // open file to write with your write cursor positioned at the beginning of the file

o   int outp = open("file1.txt", O_RDWR  )

§  // open file to read and write, and start the cursor for both at the beginning of the file

o   int outp = open("file1.txt", O_RDONLY  )

§  // open file to read, and start the cursor at the beginning of the file

·         flags – separate by |

o   O_RDONLY : Read only

o   O_WRONLY : Write only

o   O_RDWR : Read and write

o   O_APPEND :  Only allow write past end of file

o   O_TRUNC: wipe out file and all the space it takes

o   O_CREAT: Create the file with the mode permissions if file does not exist

o   O_EXCL : With O_CREATE, will fail if the file exists

·         Mode

o   separate by |

o   mode is only needed for creation of a file

o   see result in ls -l

o   permissions may be disallowed by UMASK – type umask to see your permissions

 

Owner

Group

Others

Read Permission

S_IRUSR

S_IRGRP

S_IROTH

Write Permission

S_IWUSR

S_IWGRP

S_IWOTH

Execute Permission

S_IXUSR

S_IXGRP

S_IXOTH

 

·         -1 is error

·         Good return gives the file descriptor #

Examples: (You can look at the sample files at the location given below)

·         simple open: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/create_file.c

·         examine file descriptors: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/create_file_many.c

·         Take a look at file descriptors : cd /proc/your process id found via ps

Write

·         numwritten = write(fd, buffer, count);

·         example: char buf[] = "what I want to write"; int numwritten = write(outp,buf,sizeof(buf));

·         Note that if your buffer is a char * then you will want to use strlen not sizeof.

·         -1 is error

·         Good return gives the number of characters written to the file

·         Examples:

o   Example of using write to write to the screen: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/simple_write.c

§  experiment with command line redirection

o   Example of using write to write to a file: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/simple_write_file.c

 

Close

·         status = close(fd);

Read

·         numRead = read(fd, buffer, count);

·         example: char buf[20]; int numRead = read(inp,buf,sizeof(buf));

o   note that you want sizeof(buf), not strlen(buf) because the buffer is currently empty.

·         -1 is error

·         Good return gives the number of characters read into the buffer.

·         after the read, your buffer is filled with the value read into it.

·         Your buffer must have memory allocated – use a character array of definite size

·         Examples:

o   example of reading screen using read: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/simple_read.c

§  experiment with redirection on the call

o   example of reading file using read and writing using write: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/copy_system.c

o   Another example using a larger block: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/copy_block.c

o   Example of getting the file name in different ways: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile2.c

o   Example of reading a fixed layout and making a change: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile3_onerecord.c

o   Example of reading repeatedly until the end of the file: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile3.c

o   Example of reading until /n: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoreadline.c

§  Why it does not work to just read to the end of the line: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoreadlinechunk.c

o   Example of using a structure to read and write a fixed layout: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile3.c

o   Example of removing a record from a fixed record layout: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoremovefixed.c

o   Example of removing a record from a non-fixed layout: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoremovenonfixed.c

o   Example of creating a menu: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/menuwork.c

 

lseek

·         #include <sys/types.h>

·         #include <unistd.h>

·         off_t lseek(int fd, off_t offset, int whence);

·         example: int exactOffset = lseek(fd,15,SEEK_CUR);

·         -1 is error

·         Whence

o   SEEK_SET – from 0; SEEK_CUR – from current offset ; SEEK_END from end

·         Examples

o   Example of using seek to write after the start of the file: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/lseek_huge.c

o   Example of using seek to change a particular record: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/timestampwithseek.

§  first create the file to read using : wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/timestamp.c

 

fstat

·         fstat(file descriptor, pointer to a variable of type struct stat)

·         Make a structure  to receive the status info:

o   struct stat     file_info;

·         call the fstat command to fill the structure

o   fstat (fd, &file_info);

·         similar commands:

o   fstat reports on open files

o   lstat on the link, not the file itself

o   stat on a file in a directory

·         Inside the structure, find:

o   st_mode contains the file’s access permissions and the file type in the higher-order bits. 

o   st_uid and st_gid contain uid (user id number) and gid group id number)

o   st_size contains the file size, in bytes.

o   st_atime contains the time when this file was last accessed (read or written).

o   st_mtime contains the time when this file was last modified.

o   st_dev contains the major and minor device number of the hardware device

o   st_ino contains the inode number of this file.

o   example find size: size_t size = file_info.st_size;

·         Determine file type:  (can call S_ISDIR (file_info.st_mode) or other file type macros)

o   S_ISBLK (mode)  - block device

o   S_ISCHR (mode)  - character device

o   S_ISDIR (mode)  - directory

o   S_ISFIFO (mode) - fifo (named pipe)

o   S_ISLNK (mode)  - symbolic link

o   S_ISREG (mode)  - regular file

o   S_ISSOCK (mode)  - socket

o   Example:

§  if (S_ISDIR (file_info.st_mode))

§                  return "directory";

·         Examples:

o   check if regular file: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/readfile.c

o   check if directory: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/readdirectory.c

o   https://www.lix.polytechnique.fr/~liberti/public/computing/prog/c/C/FUNCTIONS/stat.html

 

link:

·         creates a new name for a file linked to an existing file

·         link (old, new) returns -1 if error

·         to rename – link (old,new); unlink(old);

unlink

·         removes a row from the open file table

·         If it is the last open file pointing to a particular file in memory, it removes the file in memory as well as the open file row.

·         Example: rename a file: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demorename.c

Directories:

•          include <dirent.h>

•          opendir() - returns a DIR* handle, which can be used to access the directory contents.

–        If an error occurs, the call returns NULL.

–        example: DIR * dir = opendir (dir_path);

•          readdir() - returns a pointer to a struct dirent instance corresponding to the next directory entry.

–        The struct dirent contains

•          d_name : the name of a file

•          d_ino : the inode number.

–        create a pointer to this structure with : struct dirent* varname;

–        read with: entry = readdir (directory_pointer)

–        get the filename from a dirent structure as the d_name inside the structure variable

–        example:

•          struct dirent* entry;

•          // assume dir is the directory pointer that was retrieved from opendir

•          while ((entry = readdir (dir)) != NULL) {

•           char* filename = entry->d_name;

•          closedir() – closes directory

–        closedir (dir);

•          Example: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/readdirectory.c

Environment variables:

·         putenv( NEWONE=Hello); sets the environment variable you specify as though you had entered the shell command: env NEWONE=Hello. See that no spaces around the = is important. return -1 if not found

 

·         getenv(HOME) ; returns the value of the environment variable.

·         Example: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/demoenvfile2.c

 

fcntl

·         Does lots, but we are using it to lock files

·         http://beej.us/guide/bgipc/output/html/multipage/flocking.html

·         include <fcntl.h>

·         create a variable of the lock type: struct flock fl;

·         setting a lock:

o   set the structure to the lock you want:

§  fl.l_type   = F_WRLCK;  /* F_RDLCK, F_WRLCK, F_UNLCK    */

§  fl.l_whence = SEEK_SET; /* SEEK_SET, SEEK_CUR, SEEK_END */

§  fl.l_start  = 0;        /* Offset from l_whence         */

§  fl.l_len    = 0;        /* length, 0 = to EOF           */

§  fl.l_pid    = getpid(); /* our PID                      */

o   then set the lock or retrieve the lock info into the structure.

§  example: fcntl(fd, F_SETLKW, &fl);  // F_GETLK (get lock info),  F_SETLK (set   lock) , F_SETLKW (set a lock but wait until the lock is available)

§  returns -1 if it cannot set the lock

·         releasing a lock:

o   set the structure to indicate unlock: fl.l_type   = F_UNLCK;  /* tell it to unlock the region */

o   call fcntl again

§  example: fcntl(fd, F_SETLKW, &fl); 

§  returns -1 if it cannot unset the lock

·         Example: wget http://home.adelphi.edu/~pe16132/csc271/note/scripts/fileio/lockdemo.c

 

C variable types we will use:

int

double

char

char[#] : for a character array that allocates memory when created with a number inside brackets

char * : for a character array that does not allocate memory now. Later set to a string literal or allocate memory with malloc

                char * x; x = (char *) (malloc (sizeof(char) * 30))

struct ? : create a type that has parts which are other variable types

create the struct type first using : struct name { int x; int y;};

create a variable of that type : struct name myvar;

use the type: myvar.x and myvar.y

C functions we will use:

Character functions: requires #include <ctype.h> http://www.tutorialspoint.com/c_standard_library/ctype_h.htm

toupper(char x) returns the uppercase version of x

tolower(char x) returns the lowercase version of x

isupper(char x) returns 0 when x is not uppercase

islower(char x) returns 0 when x is not lowercase

                String functions: requires #include <string.h>  http://www.tutorialspoint.com/c_standard_library/string_h.htm

strcpy (to, from) copies the "from" string to the "to" string and returns a pointer to the "to" string. Error is a NULL return.

strlen(string) returns the length of  a string. It is looking for the first '\0' (NULL) to end the string.

strstr(string to search, string to find) returns a pointer to the first occurrence. You can give it a char * or char[], but you must take the answer back as a char *. It is actually just pointing to the original string, and is not a new string of its own.

memset (array , 0,SIZE ) to initials character array to nulls. 

strcspn(string to search, character(s) to find) returns the index of the first occurrence of any of the characters in the second parameter. ex: strcspn("word","o") will return 1.  

                Standard I/O functions: requires #include <stdio.h> http://www.tutorialspoint.com/c_standard_library/stdio_h.htm

printf ("format string", a variable for each % in the format string) writes to the screen. %d is an integer, %lf is a double, %c is a character, %s is a string

puts("a string to write") writes to the screen with no variable content.

malloc(size) returns a pointer to a void type of the requested size. Upon error, it returns NULL.

C Program Structure:

·         No classes

·         A main method is required.

o   If you want to read the arguments passed upon calling, include main(int argc, char *argv[])

§  argc is number of arguments calculated by the system

§  argv is an array of the arguments

§  ex: ./myprogram abc def –a –lr 'a var with space '

§  the dash is ignored so the third parm in example is a

§  the last parm is all taken as one 'a var with space ' because of the single quotes

§  the third parm is lr

·         No String

·         If structure is the same.

·         switch (var) { case ? :  do something; break; default: do something; break; }

·         for – same but cannot shortcut to create counter inside the loop

·         #define <keyword> <translation>  Use the keyword in the code.