Difference between revisions of "Coding Contest 25 novembre 2016"

From Sistemi Operativi
Jump to navigation Jump to search
(Created page with "== Esercizio 1 == scrivere un programma che passato come parametro il path di una directory (cwd se manca il paramtro) stampi il path relativo di tutti i file con nome palind...")
 
Line 35: Line 35:
  
 
Trovare i file di contenuto uguale nella directory corrente e convertirli in link dello stesso file.
 
Trovare i file di contenuto uguale nella directory corrente e convertirli in link dello stesso file.
 +
 +
Esempio di soluzione dell'esercizio [[User:Renzo|Renzo]] ([[User talk:Renzo|talk]]) 09:06, 6 December 2016 (CET).
 +
(in aula sembrava avere un bug ma non era vero. Alcuni file in /tmp non sono stati convertiti in link perché appartenevano ad altro utente).
 +
 +
<syntaxhighlight lang=C>
 +
#include <stdio.h>
 +
#include <fcntl.h>
 +
#include <stdlib.h>
 +
#include <unistd.h>
 +
#include <stdarg.h>
 +
#include <string.h>
 +
#include <libgen.h>
 +
#include <errno.h>
 +
#include <dirent.h>
 +
#include <mhash.h>
 +
#include <sys/types.h>
 +
#include <sys/stat.h>
 +
 +
struct file {
 +
  struct file *next;
 +
  unsigned char hash[20];
 +
  char *name;
 +
};
 +
 +
struct file *head;
 +
 +
static int ckcontents(int fd1, int fd2) {
 +
  char buf1[BUFSIZ],buf2[BUFSIZ];
 +
  ssize_t n1, n2;
 +
  do {
 +
    n1 = read(fd1, buf1, BUFSIZ);
 +
    n2 = read(fd2, buf2, BUFSIZ);
 +
  } while (n1 == n2 && n1 > 0 && memcmp(buf1, buf2, n2 == 0));
 +
  return n1 == n2;
 +
}
 +
 +
static int cksize(int fd1, int fd2) {
 +
  struct stat st1, st2;
 +
  return
 +
    fstat(fd1, &st1) == 0 &&
 +
    fstat(fd2, &st2) == 0 &&
 +
    st1.st_size == st2.st_size;
 +
}
 +
 +
int filecmp(char *path1, char *path2) {
 +
  int fd1 = open(path1, O_RDONLY);
 +
  int fd2 = open(path2, O_RDONLY);
 +
  int rval =
 +
    fd1 >= 0 && fd2 >=0 && cksize(fd1, fd2) && ckcontents(fd1, fd2);
 +
  close(fd1);
 +
  close(fd2);
 +
  return rval;
 +
}
 +
 +
#if 0
 +
void printhash(unsigned char * hash) {
 +
  int i;
 +
  for (i = 0; i < mhash_get_block_size(MHASH_SHA1); i++)
 +
    printf("%.2x", hash[i]);
 +
}
 +
#endif
 +
 +
void compute_sha1sum(char *path, char *hash) {
 +
  int fd;
 +
  MHASH td;
 +
  if ((fd = open(path, O_RDONLY)) >= 0) {
 +
    if ((td = mhash_init(MHASH_SHA1)) != MHASH_FAILED) {
 +
      ssize_t n;
 +
      char buf[BUFSIZ];
 +
      while ((n = read(fd, buf, BUFSIZ)) > 0)
 +
        mhash(td, buf, n);
 +
      mhash_deinit(td, hash);
 +
    }
 +
    close(fd);
 +
  }
 +
}
 +
 +
static void check_n_link(char *name) {
 +
  struct file **scan;
 +
  unsigned char hash[20];
 +
  compute_sha1sum(name, hash);
 +
  for (scan = &head; *scan != NULL; scan = &((*scan) -> next)) {
 +
    //printhash((*scan)->hash); printf(" - "); printhash(hash); printf("\n");
 +
    if (memcmp((*scan)->hash, hash, 20) == 0 &&
 +
        filecmp((*scan)->name, name)) {
 +
      unlink(name);
 +
      link((*scan)->name, name);
 +
      printf("%s and %s have the same contents\n", (*scan)->name, name);
 +
      return;
 +
    }
 +
  }
 +
  *scan = malloc(sizeof(struct file));
 +
  if (*scan) {
 +
    (*scan)->next = NULL;
 +
    memcpy((*scan)->hash, hash, 20);
 +
    (*scan)->name = name;
 +
    //printf("%s\n",name);
 +
  }
 +
}
 +
 +
static void freefilelist() {
 +
  while (head) {
 +
    struct file *delenda;
 +
    delenda = head;
 +
    head = head->next;
 +
    free(delenda);
 +
  }
 +
}
 +
 +
void err_exit(char *fmt, ...) {
 +
  va_list ap;
 +
 +
  va_start(ap, fmt);
 +
  vfprintf(stderr, fmt, ap);
 +
  va_end(ap);
 +
  exit(2);
 +
}
 +
 +
static int regular_only(const struct dirent *d) {
 +
  const char *name = d->d_name;
 +
  struct stat st;
 +
  return stat(name, &st) == 0 && S_ISREG(st.st_mode);
 +
}
 +
 +
int main(int argc, char *argv[]) {
 +
  struct dirent **list;
 +
  int n;
 +
  int i;
 +
  n = scandir(".", &list, regular_only, alphasort);
 +
  if (n > 0) {
 +
    for (i=0; i<n; i++) {
 +
      char *name = list[i]->d_name;
 +
      check_n_link(name);
 +
    }
 +
    freefilelist();
 +
    for (i=0; i<n; i++)
 +
      free(list[i]);
 +
    free(list);
 +
  }
 +
}
 +
 +
</syntaxhighlight>

Revision as of 09:06, 6 December 2016

Esercizio 1

scrivere un programma che passato come parametro il path di una directory (cwd se manca il paramtro) stampi il path relativo di tutti i file con nome palindromo presenti nel sottoalbero.


2720c84e673c75c20a27a07ffcd6826b31c8babc esercizio1.c Leonardo (talk) 17:23, 25 November 2016 (CET)

86aca4384a296bf12c69541fc5418fe4b6656e0d es1.c Fabio.capucci (talk) 17:30, 25 November 2016 (CET)

071fccfe63b8121f951444cb57001ccdd4ec02d0 Es1.c FilippoB (talk) 17:31, 25 November 2016 (CET)

235f2414cfe5b81973b1d388ce9431aa02b5f305 MatteoC (talk) 17:43, 25 November 2016 (CET)

168d3422b92fc78519e19d6a8e156b260a7798a6 testdir.c Tamino (talk) 18:06, 25 November 2016 (CET)

Esercizio 2

lancia tutti gli eseguibili della directory passata come primo paramtro e concatena gli output. (i parametri rimanenti devono essere passati a tutti gli eseguibili)

lanciatutti dir 1 2 3

se nella directory dir sono presenti a, b e c (eseguibili) lancia a 1 2 3', b 1 2 3, c 1 2 3

Esercizio 3

Scrivere un programma che deve ottenere il pid passato come parametro. indicare se e' impossibile

fdf7b609e470c43a32a50801e76e78c32aebfbb1 main.tar.gz Alexp (talk) 17:22, 25 November 2016 (CET)

Esercizio 4

Trovare i file di contenuto uguale nella directory corrente e convertirli in link dello stesso file.

Esempio di soluzione dell'esercizio Renzo (talk) 09:06, 6 December 2016 (CET). (in aula sembrava avere un bug ma non era vero. Alcuni file in /tmp non sono stati convertiti in link perché appartenevano ad altro utente).

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>
#include <libgen.h>
#include <errno.h>
#include <dirent.h>
#include <mhash.h>
#include <sys/types.h>
#include <sys/stat.h>

struct file {
  struct file *next;
  unsigned char hash[20];
  char *name;
};

struct file *head;

static int ckcontents(int fd1, int fd2) {
  char buf1[BUFSIZ],buf2[BUFSIZ];
  ssize_t n1, n2;
  do {
    n1 = read(fd1, buf1, BUFSIZ);
    n2 = read(fd2, buf2, BUFSIZ);
  } while (n1 == n2 && n1 > 0 && memcmp(buf1, buf2, n2 == 0));
  return n1 == n2;
}

static int cksize(int fd1, int fd2) {
  struct stat st1, st2;
  return
    fstat(fd1, &st1) == 0 &&
    fstat(fd2, &st2) == 0 &&
    st1.st_size == st2.st_size;
}

int filecmp(char *path1, char *path2) {
  int fd1 = open(path1, O_RDONLY);
  int fd2 = open(path2, O_RDONLY);
  int rval =
    fd1 >= 0 && fd2 >=0 && cksize(fd1, fd2) && ckcontents(fd1, fd2);
  close(fd1);
  close(fd2);
  return rval;
}

#if 0
void printhash(unsigned char * hash) {
  int i;
  for (i = 0; i < mhash_get_block_size(MHASH_SHA1); i++) 
    printf("%.2x", hash[i]);
}
#endif

void compute_sha1sum(char *path, char *hash) {
  int fd;
  MHASH td;
  if ((fd = open(path, O_RDONLY)) >= 0) {
    if ((td = mhash_init(MHASH_SHA1)) != MHASH_FAILED) {
      ssize_t n;
      char buf[BUFSIZ];
      while ((n = read(fd, buf, BUFSIZ)) > 0)
        mhash(td, buf, n);
      mhash_deinit(td, hash);
    }
    close(fd);
  }
}

static void check_n_link(char *name) {
  struct file **scan;
  unsigned char hash[20];
  compute_sha1sum(name, hash);
  for (scan = &head; *scan != NULL; scan = &((*scan) -> next)) {
    //printhash((*scan)->hash); printf(" - "); printhash(hash); printf("\n");
    if (memcmp((*scan)->hash, hash, 20) == 0 &&
        filecmp((*scan)->name, name)) {
      unlink(name);
      link((*scan)->name, name);
      printf("%s and %s have the same contents\n", (*scan)->name, name);
      return;
    }
  }
  *scan = malloc(sizeof(struct file));
  if (*scan) {
    (*scan)->next = NULL;
    memcpy((*scan)->hash, hash, 20);
    (*scan)->name = name;
    //printf("%s\n",name);
  }
}

static void freefilelist() {
  while (head) {
    struct file *delenda;
    delenda = head;
    head = head->next;
    free(delenda);
  }
}

void err_exit(char *fmt, ...) {
  va_list ap;

  va_start(ap, fmt);
  vfprintf(stderr, fmt, ap);
  va_end(ap);
  exit(2);
}

static int regular_only(const struct dirent *d) {
  const char *name = d->d_name;
  struct stat st;
  return stat(name, &st) == 0 && S_ISREG(st.st_mode);
}

int main(int argc, char *argv[]) {
  struct dirent **list;
  int n;
  int i;
  n = scandir(".", &list, regular_only, alphasort);
  if (n > 0) {
    for (i=0; i<n; i++) {
      char *name = list[i]->d_name;
      check_n_link(name);
    }
    freefilelist();
    for (i=0; i<n; i++)
      free(list[i]);
    free(list);
  }
}