CSCE 313 Lecture 14

From Notes
Jump to navigation Jump to search

« previous | Tuesday, March 6, 2012 | next »

Filesystem Access Protection

3 properties

  1. Read
  2. Write
  3. Execute (enter directory)

3 targets for permissions

  • Owner
  • Group
  • Others

UNIX Special Files

Pipes

A file with two file descriptors: use fildes[1] to write to pipe, and use fildes[0]to read from pipe.

#include <unistd.h>

// int pipe(int fildes[2]);
// use fildes[0] for reading and fildes[1] for writing

int main (int argc, char **argv)
{
    int fd[2]; char result[MAX_LENGTH];
    pipe(fd);
    if (fork()) {
        fprintf(fd[1], "I am writing into the pipe\n");
    } else {
        fscanf("%s", result);
        printf("I read <%s> from the pipe.\n", result);
    }

    return 0;
}

Pipes can be used for synchronization:

int main(int argc, char **argv)
{
    int fd[2];
    n = atoi(argv[1]);
    pipe(fd);
    for (int i=1; i<n; i++) {
        // create a fan of processes
        if ((childpid = fork()) <= 0) break;
    }
    
    if (childpid > 0) {
        // parent writes synchronization characters into the pipe
        for (int j=0; j<n; j++) {
            write(fd[1], "g", 1);
        }
    }

    // everybody synchronizes here
    read(fd[0], buf, 1);

    return 0;
}

Pipes are used in content redirection:

# sort a list of files using redirection
ls -l > my.file
sort -n +4 < my.file

# sort a list of files using a pipe
ls -l | sort -n +4

Named Pipes (FIFOs)

Pipes are temporary, but FIFOs persist even after all processes have closed.

#include <sys/stat.h>

int mkfifo(const char *path, mode_t mode);

// server program
int main(int argc, char **argv)
{
    int requestfd;
    string fifoname = argv[1];
    // create named pipe
    mkfifo(fifoname, FIFO_PERMS);
    // open read/write endpoint to pipe
    requestfd = open(fifoname, O_RDWR);
    // write incoming info to stdout
    copy_file(requestfd, STDOUT_FILENO);
}

// client program
int main(int argc, char **argv) {
    int requestfd;
    string fifoname = argv[1];
    // open read/write endpoint to pipe
    requestfd = open(fifoname, O_WRONLY);
    log_info = generate_some_log_info();
    // send log info to server program (atomic write)
    r_write(requestfd, log_info);
    r_close(requestfd);
}
# use the following bash command to make a FIFO pipe:
mkfifo /path/to/fifofile

# sample usage (note that process will block until the info has been read)
ls -l > testpipe &

cat < testpipe

Device Control

Example: /dev/audio

Access through filesystem: cat sample.au > /dev/audio

Under the code:

// open audio device like a file
int open_audio(void) {
    while (((audio_fd = open("/dev/audio", O_RWR)) == -1) && (errno  == EINTR));
    if (audio_fd == -1) return -1;
    return 0;
}

// use ioctl to access and manipulate device parameters
unit_t get_sample_rate(void) {
    audio_info_t myaudio;
    ioctl(audio_fd, AUDIO_GETINFO, &myaudio);
    return myaudio.play.sample_rate;
}