ProvaPratica 2011.01.19

From Sistemi Operativi
Jump to navigation Jump to search

TESTO COMPITO

Esercizio 1

// Dependencies
#include "../const.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <getopt.h>

// Function declarations
static inline void printAndDie(const char *msg);
static inline void errorAndDie(const char *msg);
static void redirectAndRun(char *outFile, char *inFile, char *path, char *command[]);
static void parseArguments(int argc, char **argv);

// Entry point
extern void run(int argc, char *argv[])
{
	parseArguments(argc, argv);
}

/*
 * Parse arguments accordingly to a given set of options.
 * Input: argc, the argument counter
 *        argv, the argument vector
 */
static void parseArguments(int argc, char **argv)
{
	int i, j, result;
	char **command;
	char *fileName, *outFile, *inFile;

	// Short-named options
	const char *shortOptions = "o:i:h";
	// Long-named options
	static struct option longOptions[] =
	{
		{"in",		required_argument, 0,  'i' },
		{"out",		required_argument, 0,  'o' },
		{"help",	no_argument, 	   0,  'h' },
		{0,         0,                 0,   0  }
	};

	result = True;
	outFile = inFile = NULL;

	// Disable default error message
	opterr = 0;

	// Parse options
	result = getopt_long(argc, argv, shortOptions, longOptions, NULL);
	if (result < 0)
		printAndDie("Wrong input. Run 'redir -h' for help.");

	j = 1;
	while (result != -1 && result != '?')
	{
		// Get the option value
		switch (result)
		{
		case 'i':
			inFile = optarg;
			j = optind;
			break;
		case 'o':
			outFile = optarg;
			j = optind;
			break;
		case 'h':
			printf("Usage: [options] command\n");
			printf(" options:\n");
			printf("  -i --in    required_argument   Redirect input.\n");
			printf("  -o --out   required_argument   Redirect output.\n");
			printf("  -h --help  no_argument         Show this help.\n");
			exit(EXIT_SUCCESS);
		}
		result = getopt_long(argc, argv, shortOptions, longOptions, NULL);
	}

	// Parse command
	command = (char **) malloc((argc - optind + 1) * sizeof (char *));
	fileName = argv[j];
	i = 0;
	while (j < argc)
		command[i++] = argv[j++];
	command[i] = NULL;

	redirectAndRun(outFile, inFile, fileName, command);
}

/*
 * Re-direct [input, output] and run a command
 * Input: outFile, output file
 *        inFile,  input file
 *        command, command
 *        args,    command arguments
 */
static void redirectAndRun(char *outFile, char *inFile, char *command, char *args[])
{
	int pid, outFD, inFD;

	outFD = inFD = 0;
	if (inFile)
	{
		inFD = open(inFile, O_RDONLY);
		if (inFD < 0)
			errorAndDie("open");
	}
	if (outFile)
	{
		outFD = open(outFile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
		if (outFD < 0)
			errorAndDie("open");
	}

	if ((pid = fork()) < 0)
		errorAndDie("fork");

	// Child process
	if (pid == 0)
	{
		if (inFile)
		{
			if (dup2(inFD, STDIN_FILENO) < 0)
				errorAndDie("dup2");

			if (close(inFD) < 0)
				 errorAndDie("close");
		}
		if (outFile)
		{
			if (dup2(outFD, STDOUT_FILENO) < 0)
				errorAndDie("dup2");
			if (close(outFD) < 0)
				 errorAndDie("close");
		}
	    execvp(command, args);
	    errorAndDie("execvp");
	}

	// Parent process
	if (inFile)
		if (close(inFD) < 0)
			 errorAndDie("close");
	if (outFile)
		if (close(outFD) < 0)
			 errorAndDie("close");
}

/*
 * Print error message and exit
 * Input: msg, the error message
 */
static inline void errorAndDie(const char *msg)
{
	perror(msg);
	exit(EXIT_FAILURE);
}

/*
 * Print message and exit
 * Input: msg, the message
 */
static inline void printAndDie(const char *msg)
{
	printf("%s\n", msg);
	exit(EXIT_FAILURE);
}

Esercizio 3

import os, sys

'''
@summary: Walk through a directory tree.
          Populate a dictionary with key-value pair 
          { file name - (last modification - directory) }.
          Create soft links of the last modified files in a destination directory.
@param sources:     list of source directories  
@param n:           number of source directories
@param destination: the destination directory
'''
def MergeDirectories(sources, n, destination):
    # Populate the dictionary
    fileLastMod = {}
    
    for i in range(0, n):
        for fileName in os.listdir(sources[i]):
            filePath = os.path.join(sources[i], fileName)
            lastMod = os.path.getmtime(filePath)
            if fileLastMod.get(fileName, None) == None:
                fileLastMod[fileName] = (lastMod, sources[i])
            elif fileLastMod[fileName][0] < lastMod:
                fileLastMod[fileName] = (lastMod, sources[i])
           
    # Generate the soft links
    for key, value in fileLastMod.items():
        srcPath = os.path.join(value[1], key)
        dstPath = os.path.join(destination, key)
        if not os.path.lexists(dstPath):
            os.symlink(srcPath, dstPath)

# Entry point
def Main(argv, argc):
    
    # Perform a sanity check and parse the parameters
    if argc < 4:
        sys.exit("The function requires at least three parameters to be passed in.")

    last = argc - 1
    source = []
    for i in range(1, last):      
        if not os.path.isabs(argv[i]):
            source.append(os.path.abspath(argv[i]))
        else:
            source.append(argv[i])
            
        if not os.path.isdir(source[i - 1]):
            sys.exit("The parameters should be existing directories.") 
            
    destination = argv[last]     
   
    MergeDirectories(source, last - 1, destination)
            
    print("Done!")

if __name__ == "__main__":
    sys.exit(Main(sys.argv, len(sys.argv)))