1737 lines
39 KiB
C
1737 lines
39 KiB
C
#define _POSIX_C_SOURCE 200809L
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/time.h>
|
|
#include <sys/un.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
#include <math.h>
|
|
|
|
#include "api.h"
|
|
#include "conn.h"
|
|
|
|
#define SOCKNAMEMAX 256 /* should be at least 108 */
|
|
|
|
|
|
#define MEOK "20" /*OK */
|
|
// #define ME "21" /* not used */
|
|
// #define ME "22" /* not used */
|
|
#define MEFP "25" /* file purged */
|
|
|
|
// #define ME "40" /* not used */
|
|
// #define ME "41" /* not used */
|
|
#define MESD "42" /* shutting down */
|
|
#define MENT "45" /* requested file action not taken */
|
|
|
|
#define MESY "50" /* syntax error */
|
|
// #define ME "51" /* not used */
|
|
// #define ME "52" /* not used */
|
|
#define MESE "55" /* server error */
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// structs
|
|
|
|
typedef struct files_s {
|
|
char *filename;
|
|
int locked;
|
|
struct files_s *next;
|
|
} files_t;
|
|
|
|
typedef struct openfiles_s {
|
|
int numOfFiles;
|
|
files_t *f; /* list of files that are currently opened */
|
|
int validwDir; /* true if wDir is allocated */
|
|
char *wDir; /* for files sent from the server after openFile */
|
|
int validrDir; /* true if rDir is allocated */
|
|
char *rDir; /* for files read from the server */
|
|
char *createdAndLocked; /* path of the last file that was created and locked */
|
|
int print; /* whether to print */
|
|
FILE *out; /* where to print */
|
|
} openfiles_t;
|
|
|
|
/* struct for the files sent from the server */
|
|
typedef struct recivedFile_s {
|
|
int64_t pathlen;
|
|
char *path;
|
|
int64_t filelen;
|
|
char *file;
|
|
} recivedFile_t;
|
|
|
|
typedef struct response_s {
|
|
char ME[2]; /* response */
|
|
int meerrno; /* errno sent by server */
|
|
int64_t numfiles; /* number of files if sent */
|
|
recivedFile_t *rf; /* array of files */
|
|
} response_t;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// global variables
|
|
static long fd_skt; /* descriptor of the socket */
|
|
static char socketName[SOCKNAMEMAX] = ""; /* name of the socket */
|
|
static openfiles_t *openedFiles = NULL;
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// helper functions
|
|
|
|
/* closes every file opened by the client */
|
|
int closeEveryFile();
|
|
/* closes and frees memory */
|
|
int removeOpenFile(const char *);
|
|
/* adds element */
|
|
int addOpenFile(const char *, const int);
|
|
/* checks if the file is open already */
|
|
int isOpen(const char *, const int);
|
|
/* reads everything the server sent into the variable passed to the function
|
|
* expected == 1 if a file should be sent (if no server errors occurs) */
|
|
int reciveData(response_t *, int expected);
|
|
/* saves the files in the specified directory */
|
|
int storeFilesInDirectory(const char *, int n, recivedFile_t *);
|
|
/* frees memory inside response_t element */
|
|
void freeResponse(response_t *);
|
|
/* initiates the global variables */
|
|
int createOpenedFiles();
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
int openConnection(const char* sockname, int msec, const struct timespec abstime) {
|
|
if(!sockname){
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if(!openedFiles) {
|
|
if(createOpenedFiles()<0) {
|
|
perror("openConnection: createOpenedfiles");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
struct sockaddr_un sa;
|
|
struct timespec ts;
|
|
ts.tv_sec = msec/1000;
|
|
ts.tv_nsec = (msec % 1000) * 1000000;
|
|
struct timeval t1, t2; /* for gettimeofday */
|
|
long long start, end; /* to calculate the time elapsed */
|
|
long long elapsedTime;
|
|
|
|
/* select socket */
|
|
strncpy(sa.sun_path, sockname, sizeof(sa.sun_path)-1);
|
|
sa.sun_family = AF_UNIX;
|
|
|
|
if ((fd_skt = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
|
|
errno = EINVAL;
|
|
perror("openConnection: socket");
|
|
return -1;
|
|
}
|
|
|
|
if(gettimeofday(&t1, NULL) != 0) {
|
|
perror("openConnection: gettimeofday");
|
|
return -1;
|
|
}
|
|
|
|
start = (long long) (t1.tv_sec * 1000000000 + t1.tv_usec * 1000);
|
|
|
|
while (connect(fd_skt, (struct sockaddr*) &sa, sizeof(sa)) == -1) {
|
|
gettimeofday(&t2, NULL);
|
|
end = (long long) t2.tv_sec * 1000000000 + t2.tv_usec * 1000;
|
|
elapsedTime = (end - start);
|
|
|
|
/* return if more time has elapsed than allowed */
|
|
if (elapsedTime > (abstime.tv_sec * 1000000000) + abstime.tv_nsec) {
|
|
errno = ETIMEDOUT;
|
|
return -1;
|
|
}
|
|
|
|
nanosleep(&ts, &ts);
|
|
}
|
|
|
|
strncpy(socketName, sockname, sizeof(socketName)-1);
|
|
return 0;
|
|
}
|
|
|
|
int closeConnection(const char* sockname) {
|
|
if (!sockname) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
/* if closing a different socket -> error */
|
|
if(strncmp(socketName, "", sizeof(socketName)) != 0
|
|
&& strncmp(socketName, sockname, sizeof(socketName)) != 0) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
/* close every file */
|
|
if (closeEveryFile() == -1) {
|
|
perror("closeConnection: closeEveryFile");
|
|
return -1;
|
|
}
|
|
/* close socket */
|
|
if (close(fd_skt) == -1) {
|
|
/* return errno from close */
|
|
return -1;
|
|
}
|
|
|
|
memset(socketName, 0, SOCKNAMEMAX);
|
|
return 0;
|
|
}
|
|
|
|
int openFile(const char* pathname, int flags) {
|
|
if(!pathname){
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
if(isOpen(pathname, flags) == 1) { /* already open */
|
|
return 0;
|
|
}
|
|
|
|
/* sent to server the string "openFile|$(pathname)|$(flags)" */
|
|
int leng_flags = snprintf(NULL, 0, "%d", flags);
|
|
long len = strlen("openFile")+1+strlen(pathname)+1+leng_flags+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("openFile: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "openFile|%s|%d", pathname, flags);
|
|
len = strnlen(cmd, len);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("openFile: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we dont expect a file */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) {
|
|
/* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(strncmp(res->ME, MEFP, sizeof(res->ME)) == 0) {
|
|
/* some files were purged */
|
|
if(openedFiles->print){
|
|
fprintf(openedFiles->out, "\nIl server ha espulso i seguenti file:\n");
|
|
fflush(openedFiles->out);
|
|
for(int i=0;i<res->numfiles;++i) {
|
|
fprintf(openedFiles->out, "\t%d) %s\n", i+1, res->rf[i].path);
|
|
}
|
|
}
|
|
if(openedFiles->wDir) {
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "\tI file espulsi sono stati scritti nella cartella: %s\n", openedFiles->wDir);
|
|
fflush(openedFiles->out);
|
|
}
|
|
if(storeFilesInDirectory(openedFiles->wDir, res->numfiles, res->rf) == -1) {
|
|
perror("openFile: storeFilesindirectory");
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
} else {
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "\tI file espulsi non sono stati memorizzati su disco\n");
|
|
fflush(openedFiles->out);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(addOpenFile(pathname, flags) == -1) {
|
|
perror("openFile: addOpenFile");
|
|
return -1;
|
|
}
|
|
|
|
if(flags == (O_CREATE | O_LOCK)) {
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = calloc(strlen(pathname)+1, sizeof(char));
|
|
if(!openedFiles->createdAndLocked) {
|
|
perror("openFile: calloc");
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
strcpy(openedFiles->createdAndLocked, pathname);
|
|
}
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
|
|
free(cmd);
|
|
return 0;
|
|
}
|
|
|
|
int readFile(const char* pathname, void** buf, size_t* size) {
|
|
if(!pathname) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
|
|
if(isOpen(pathname, 0) != 1) { /* if it's not open => error */
|
|
errno = EPERM;
|
|
return -1;
|
|
}
|
|
|
|
/* send to server the string readFile|$(pathname)" */
|
|
long len = strlen("readFile")+1+strlen(pathname)+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("readFile: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "readFile|%s", pathname);
|
|
len = strnlen(cmd, len);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("readFile: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 1) because if we get a MEOK we expect a file */
|
|
if(reciveData(res, 1) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) { /* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* no errors from server */
|
|
if(res->numfiles != 1) {
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
errno = EMSGSIZE;
|
|
return -1;
|
|
}
|
|
*size = (size_t) res->rf[0].filelen;
|
|
*buf = malloc(*size);
|
|
if(!*buf) {
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
perror("readFile: malloc");
|
|
return -1;
|
|
}
|
|
memcpy(*buf, res->rf[0].file, *size);
|
|
if(openedFiles->print) {
|
|
printf("Letto il file: %s\n", res->rf[0].path);
|
|
printf("Di dimensione: %ld B\n", *size);
|
|
fflush(openedFiles->out);
|
|
}
|
|
if(openedFiles->rDir) {
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "Il file letto e' stato scritto nella cartella: %s\n", openedFiles->rDir);
|
|
fflush(openedFiles->out);
|
|
}
|
|
if(storeFilesInDirectory(openedFiles->rDir, 1, res->rf) == -1) {
|
|
perror("readFile: storeFilesInDirectory");
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
} else {
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "Il file letto non è stato memorizzato su disco\n");
|
|
fflush(openedFiles->out);
|
|
}
|
|
}
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
|
|
free(cmd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int readNFiles(int N, const char* dirname) {
|
|
if(!dirname) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
|
|
/* send to server the string "readNFiles|$(N)" */
|
|
int lenght_n = snprintf(NULL, 0, "%d", N);
|
|
long len = strlen("readNFiles")+1+lenght_n+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("readNFiles: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "readNFiles|%d", N);
|
|
len = strnlen(cmd, len);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("readNFiles: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 1) because if we get a MEOK we expect N files */
|
|
if(reciveData(res, 1) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) { /* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
if(openedFiles->print){
|
|
for(int i=0;i<res->numfiles;++i) {
|
|
fprintf(openedFiles->out, "%d) %s\n", i, res->rf[i].path);
|
|
}
|
|
fflush(openedFiles->out);
|
|
}
|
|
|
|
/* save files to directory */
|
|
if(storeFilesInDirectory(dirname, res->numfiles, res->rf) == -1) {
|
|
perror("readNFiles: storeFilesindirectory");
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
int n = res->numfiles;
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
|
|
free(cmd);
|
|
return n;
|
|
}
|
|
|
|
int writeFile(const char* pathname, const char* dirname) {
|
|
if(!pathname) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if (strcmp(openedFiles->createdAndLocked, pathname) != 0) {
|
|
errno = EPERM;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
|
|
/* read the file that needs to be sent to the server */
|
|
int fdi = -1;
|
|
size_t lung = 0;
|
|
size_t incr = 0;
|
|
size_t size = 0;
|
|
|
|
if ((fdi = open(pathname, O_RDONLY)) == -1) {
|
|
perror("writeFile: open");
|
|
return -1;
|
|
}
|
|
|
|
/* get file length */
|
|
struct stat sb;
|
|
if (fstat(fdi, &sb) == -1) {
|
|
perror("writeFile: fstat");
|
|
return -1;
|
|
}
|
|
lung = sb.st_size;
|
|
|
|
void *content = malloc(lung);
|
|
if(!content) {
|
|
perror("writeFile: malloc");
|
|
return -1;
|
|
}
|
|
|
|
/* read file */
|
|
while ((incr = read(fdi, content, lung)) > 0) {
|
|
size += incr;
|
|
lung -= incr;
|
|
}
|
|
|
|
if (incr == -1) {
|
|
free(content);
|
|
return -1;
|
|
}
|
|
|
|
if (openedFiles->print) {
|
|
fprintf(openedFiles->out, "Dimensione: %ldB ", size);
|
|
fflush(openedFiles->out);
|
|
}
|
|
|
|
if (close(fdi) == -1) {
|
|
perror("writeFile: close");
|
|
free(content);
|
|
return -1;
|
|
}
|
|
|
|
/* send to server the string "writeFile|$(pathname)|$(size)" */
|
|
int leng_size = snprintf(NULL, 0, "%zu", size);
|
|
long len = strlen("writeFile")+1+strlen(pathname)+1+leng_size+1;
|
|
char *cmd = calloc(len, sizeof(char));
|
|
if(!cmd) {
|
|
perror("writeFile: calloc");
|
|
free(content);
|
|
return -1;
|
|
}
|
|
snprintf(cmd, len, "writeFile|%s|%zu", pathname, size);
|
|
len = strnlen(cmd, len);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(content);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(content);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("writeFile: calloc");
|
|
free(content);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we don't expect files */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
free(content);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) {
|
|
/* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
free(content);
|
|
return -1;
|
|
}
|
|
if(strncmp(res->ME, MEFP, sizeof(res->ME)) == 0) {
|
|
/* some files were purged */
|
|
if(openedFiles->print){
|
|
fprintf(openedFiles->out, "Il server ha espulso i seguenti file:\n");
|
|
fflush(openedFiles->out);
|
|
for(int i=0;i<res->numfiles;++i) {
|
|
fprintf(openedFiles->out, "%d) %s\n", i, res->rf[i].path);
|
|
}
|
|
}
|
|
if(dirname) {
|
|
if(storeFilesInDirectory(dirname, res->numfiles, res->rf) == -1) {
|
|
perror("writeFile: storeFilesindirectory");
|
|
freeResponse(res);
|
|
free(res);
|
|
free(content);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "I file espulsi sono stati scritti nella cartella: %s\n", dirname);
|
|
fflush(openedFiles->out);
|
|
}
|
|
} else {
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "I file espulsi non sono stati memorizzati su disco\n");
|
|
fflush(openedFiles->out);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* send file to server */
|
|
if (writen(fd_skt, content, size) == -1) {
|
|
/* errno set by writen */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
free(content);
|
|
return -1;
|
|
}
|
|
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we don't expect files */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
free(content);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) { /* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
free(content);
|
|
return -1;
|
|
}
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
|
|
free(cmd);
|
|
|
|
free(content);
|
|
return 0;
|
|
}
|
|
|
|
int appendToFile(const char* pathname, void* buf, size_t size, const char* dirname) {
|
|
if(!pathname || !buf) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
|
|
if (isOpen(pathname, 0) != 1) {
|
|
errno = EPERM;
|
|
return -1;
|
|
}
|
|
|
|
if (openedFiles->print) {
|
|
fprintf(openedFiles->out, "Dimensione: %ld B\n", size);
|
|
fflush(openedFiles->out);
|
|
}
|
|
|
|
/* send to server the string "appendToFile|$(pathname)|$(size)" */
|
|
int leng_size = snprintf(NULL, 0, "%zu", size);
|
|
long len = strlen("appendToFile")+1+strlen(pathname)+1+leng_size+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("appendToFile: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "appendToFile|%s|%zu", pathname, size);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("appendToFile: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we don't expect files */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
if(res->meerrno != 0) { /* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
if(strncmp(res->ME, MEFP, sizeof(res->ME)) == 0) {
|
|
/* some files were purged */
|
|
if(openedFiles->print){
|
|
fprintf(openedFiles->out, "Il server ha espulso i seguenti file:\n");
|
|
fflush(openedFiles->out);
|
|
for(int i=0;i<res->numfiles;++i) {
|
|
fprintf(openedFiles->out, "%d) %s\n", i, res->rf[i].path);
|
|
}
|
|
}
|
|
if(dirname) {
|
|
if(storeFilesInDirectory(dirname, res->numfiles, res->rf) == -1) {
|
|
perror("appendToFile: storeFilesindirectory");
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "I file espulsi sono stati scritti nella cartella: %s\n", dirname);
|
|
fflush(openedFiles->out);
|
|
}
|
|
} else {
|
|
if(openedFiles->print) {
|
|
fprintf(openedFiles->out, "I file espulsi non sono stati memorizzati su disco\n");
|
|
fflush(openedFiles->out);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* send file to server */
|
|
if (writen(fd_skt, buf, size) == -1) {
|
|
/* errno set by writen */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int lockFile(const char* pathname) {
|
|
if(!pathname){
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
|
|
if(isOpen(pathname, O_LOCK)){ /* file is already locked */
|
|
return 0;
|
|
}
|
|
|
|
int existing = 0;
|
|
if(isOpen(pathname, 0)){ /* file is already open */
|
|
existing = 1;
|
|
goto _unlockFile;
|
|
}
|
|
|
|
if (openFile(pathname, O_LOCK) == 0) /* open the file with the lock */
|
|
return 0;
|
|
|
|
if (errno == ENOENT) /* file created but not locked */
|
|
goto _unlockFile;
|
|
|
|
return -1; /* errno != ENOENT */
|
|
|
|
_unlockFile: {
|
|
/* send to server the string "lockFile|$(pathname)" */
|
|
long len = strlen("lockFile")+1+strlen(pathname)+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("lockFile: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "lockFile|%s", pathname);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("lockFile: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we dont expect a file */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) {
|
|
/* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
if(!existing) {
|
|
if(addOpenFile(pathname, O_LOCK) == -1) {
|
|
perror("lockFile: addOpenFile");
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int unlockFile(const char* pathname) {
|
|
if(!pathname){
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
if(isOpen(pathname, 0) != 1) { /* not open or not locked */
|
|
errno = EPERM;
|
|
return -1;
|
|
}
|
|
|
|
/* send to server the string "unlockFile|$(pathname)" */
|
|
long len = strlen("unlockFile")+1+strlen(pathname)+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("unlockFile: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "unlockFile|%s", pathname);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("unlockFile: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we dont expect a file */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) {
|
|
/* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return 0;
|
|
}
|
|
|
|
int closeFile(const char *pathname) {
|
|
if(!pathname){
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
|
|
if(isOpen(pathname, 0) != 1) { /* not open */
|
|
errno = EPERM;
|
|
return -1;
|
|
}
|
|
|
|
/* invio al server la stringa "closeFile|$(pathname)" */
|
|
long len = strlen("closeFile")+1+strlen(pathname)+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("closeFile: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "closeFile|%s", pathname);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("closeFile: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we dont expect a file */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) {
|
|
/* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
if (removeOpenFile(pathname) == -1) {
|
|
perror("closeFile: removeOpenFile");
|
|
} else {
|
|
openedFiles->numOfFiles--;
|
|
}
|
|
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int removeFile(const char* pathname) {
|
|
if(!pathname){
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
if(!openedFiles){
|
|
errno = EPROTO;
|
|
return -1;
|
|
}
|
|
if(openedFiles->createdAndLocked)
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
|
|
if(strcmp(socketName, "") == 0) {
|
|
errno = ENOTCONN;
|
|
return -1;
|
|
}
|
|
|
|
if (isOpen(pathname, 0) != 1) { /* not open */
|
|
errno = EPERM;
|
|
return -1;
|
|
}
|
|
|
|
/* send to server the string "removeFile|$(pathname)" */
|
|
long len = strlen("removeFile")+1+strlen(pathname)+1;
|
|
char *cmd = malloc(len);
|
|
if(!cmd) {
|
|
perror("removeFile: malloc");
|
|
return -1;
|
|
}
|
|
memset(cmd, 0, len);
|
|
snprintf(cmd, len, "removeFile|%s", pathname);
|
|
|
|
/* send cmd */
|
|
if (writen(fd_skt, &len, sizeof(long)) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if (writen(fd_skt, cmd, len) == -1) {
|
|
/* writen sets errno */
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* recive response */
|
|
response_t *res = calloc(1, sizeof(response_t));
|
|
if(!res){
|
|
perror("removeFile: calloc");
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
/* reciveData(, 0) because if we get a MEOK we dont expect a file */
|
|
if(reciveData(res, 0) < 0) {
|
|
/* errno is set by reciveData */
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
if(res->meerrno != 0) {
|
|
/* errno from server */
|
|
freeResponse(res);
|
|
errno = res->meerrno;
|
|
free(res);
|
|
free(cmd);
|
|
return -1;
|
|
}
|
|
|
|
if (removeOpenFile(pathname) == -1) {
|
|
perror("removeFile: removeOpenFile");
|
|
} else {
|
|
openedFiles->numOfFiles--;
|
|
}
|
|
freeResponse(res);
|
|
free(res);
|
|
free(cmd);
|
|
return 0;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
int setDirectory(char* Dir, int rw) {
|
|
if (!Dir) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (rw == 1) {
|
|
if(openedFiles->validwDir) {
|
|
free(openedFiles->wDir);
|
|
openedFiles->wDir = NULL;
|
|
openedFiles->validwDir = 0;
|
|
}
|
|
if(strncmp(Dir, "/dev/null", strlen("/dev/null")+1) == 0) {
|
|
return 0;
|
|
}
|
|
openedFiles->validwDir = 1;
|
|
openedFiles->wDir = malloc(strlen(Dir)+1);
|
|
strncpy(openedFiles->wDir, Dir, strlen(Dir)+1);
|
|
} else {
|
|
if(openedFiles->validrDir) {
|
|
free(openedFiles->rDir);
|
|
openedFiles->rDir = NULL;
|
|
openedFiles->validrDir = 0;
|
|
}
|
|
if(strncmp(Dir, "/dev/null", strlen("/dev/null")+1) == 0) {
|
|
return 0;
|
|
}
|
|
openedFiles->validrDir = 1;
|
|
openedFiles->rDir = malloc(strlen(Dir)+1);
|
|
strncpy(openedFiles->rDir, Dir, strlen(Dir)+1);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void printInfo(int p, FILE *stream) {
|
|
/* 1 prints, 0 does not print */
|
|
if(!openedFiles) {
|
|
if(createOpenedFiles()<0) {
|
|
perror("printInfo: createOpenedfiles");
|
|
return;
|
|
}
|
|
}
|
|
openedFiles->print = (p)? 1: 0;
|
|
openedFiles->out = stream;
|
|
return;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// helper functions
|
|
|
|
int reciveData(response_t *res, int expected) {
|
|
if(!res) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
int readnres;
|
|
readnres = readn(fd_skt, &res->ME, sizeof(res->ME));
|
|
if(readnres <= 0) {
|
|
/* readn sets errno */
|
|
return -1;
|
|
}
|
|
|
|
if(expected == 0) /* no file expected */
|
|
goto _nofile;
|
|
|
|
|
|
/* file is expected */
|
|
if(strncmp(res->ME, MEOK, sizeof(res->ME))==0){
|
|
/* ok response */
|
|
res->meerrno = 0;
|
|
/* get number of files sent */
|
|
readnres = readn(fd_skt, &res->numfiles, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
if(res->rf)
|
|
free(res->rf);
|
|
|
|
if(res->numfiles < 0) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
res->rf = calloc(res->numfiles, sizeof(recivedFile_t));
|
|
if(!res->rf){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
|
|
/* get files */
|
|
for(int i=0;i<res->numfiles;++i) {
|
|
/* read path */
|
|
readnres = readn(fd_skt, &res->rf[i].pathlen, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
res->rf[i].path = calloc(res->rf[i].pathlen, sizeof(char));
|
|
if(!res->rf[i].path){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
readnres = readn(fd_skt, res->rf[i].path, res->rf[i].pathlen);
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
/* we replace '/' char with '-' */
|
|
for(int j=0;j<res->rf[i].pathlen; ++j){
|
|
if(res->rf[i].path[j] == '/')
|
|
res->rf[i].path[j] = '-';
|
|
}
|
|
|
|
/* read file */
|
|
readnres = readn(fd_skt, &res->rf[i].filelen, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
if(res->rf[i].filelen == 0) {
|
|
res->rf[i].file = calloc(1, sizeof(char));
|
|
if(!res->rf[i].file){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char));
|
|
if(!res->rf[i].file){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
readnres = readn(fd_skt, res->rf[i].file, res->rf[i].filelen);
|
|
if(readnres<=0) {/* readn sets errno */
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MEFP, sizeof(res->ME))==0){
|
|
/* file purged */
|
|
res->meerrno = 0;
|
|
/* get number of files sent */
|
|
readnres = readn(fd_skt, &res->numfiles, sizeof(int));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
if(res->rf)
|
|
free(res->rf);
|
|
res->rf = calloc(res->numfiles, sizeof(recivedFile_t));
|
|
if(!res->rf){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
|
|
/* get files */
|
|
for(int i=0;i<res->numfiles;++i) {
|
|
/* read path */
|
|
readnres = readn(fd_skt, &res->rf[i].pathlen, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
res->rf[i].path = calloc(res->rf[i].pathlen, sizeof(char));
|
|
if(!res->rf[i].path){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
readnres = readn(fd_skt, res->rf[i].path, res->rf[i].pathlen);
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
/* we replace '/' char with '-' */
|
|
for(int j=0;j<res->rf[i].pathlen; ++j){
|
|
if(res->rf[i].path[j] == '/')
|
|
res->rf[i].path[j] = '-';
|
|
}
|
|
|
|
/* read file */
|
|
readnres = readn(fd_skt, &res->rf[i].filelen, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
if(res->rf[i].filelen == 0) {
|
|
res->rf[i].file = calloc(1, sizeof(char));
|
|
if(!res->rf[i].file){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char));
|
|
if(!res->rf[i].file){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
readnres = readn(fd_skt, res->rf[i].file, res->rf[i].filelen);
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MESD, sizeof(res->ME))==0){
|
|
/* server shutting down */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MENT, sizeof(res->ME))==0){
|
|
/* requested file action not taken */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MESY, sizeof(res->ME))==0){
|
|
/* syntax error */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MESE, sizeof(res->ME))==0){
|
|
/* server error */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
errno = ENOPROTOOPT;
|
|
return -2;
|
|
|
|
_nofile:
|
|
res->numfiles = 0;
|
|
if(res->rf)
|
|
free(res->rf);
|
|
res->rf = NULL;
|
|
|
|
if(strncmp(res->ME, MEOK, sizeof(res->ME))==0){
|
|
/* simple ok response */
|
|
res->meerrno = 0;
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MEFP, sizeof(res->ME))==0){
|
|
/* file purged */
|
|
res->meerrno = 0;
|
|
/* get number of files sent */
|
|
readnres = readn(fd_skt, &res->numfiles, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
|
|
if(res->rf)
|
|
free(res->rf);
|
|
res->rf = calloc(res->numfiles, sizeof(recivedFile_t));
|
|
if(!res->rf){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
/* get files */
|
|
for(int i=0;i<res->numfiles;++i) {
|
|
/* read path */
|
|
readnres = readn(fd_skt, &res->rf[i].pathlen, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
res->rf[i].path = calloc(res->rf[i].pathlen, sizeof(char));
|
|
if(!res->rf[i].path){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
readnres = readn(fd_skt, res->rf[i].path, res->rf[i].pathlen);
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
/* we replace '/' char with '-' */
|
|
for(int j=0;j<res->rf[i].pathlen; ++j){
|
|
if(res->rf[i].path[j] == '/')
|
|
res->rf[i].path[j] = '-';
|
|
}
|
|
|
|
/* read file */
|
|
readnres = readn(fd_skt, &res->rf[i].filelen, sizeof(int64_t));
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
|
|
/* file has lenght 0 -> allocate memory but dont read */
|
|
if(res->rf[i].filelen == 0) {
|
|
res->rf[i].file = calloc(1, sizeof(char));
|
|
if(!res->rf[i].file){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
continue;
|
|
}
|
|
res->rf[i].file = calloc(res->rf[i].filelen, sizeof(char));
|
|
if(!res->rf[i].file){
|
|
perror("reciveData: calloc");
|
|
return -1;
|
|
}
|
|
readnres = readn(fd_skt, res->rf[i].file, res->rf[i].filelen);
|
|
if(readnres<=0) /* readn sets errno */
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MESD, sizeof(res->ME))==0){
|
|
/* server shutting down */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MENT, sizeof(res->ME))==0){
|
|
/* requested file action not taken */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MESY, sizeof(res->ME))==0){
|
|
/* syntax error */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
if(strncmp(res->ME, MESE, sizeof(res->ME))==0){
|
|
/* server error */
|
|
readnres = readn(fd_skt, &res->meerrno, sizeof(errno));
|
|
if(readnres <= 0)/* readn sets errno */
|
|
return -1;
|
|
return 0;
|
|
}
|
|
|
|
errno = ENOPROTOOPT;
|
|
return -2;
|
|
}
|
|
|
|
int storeFilesInDirectory(const char *dirname, int n, recivedFile_t *rf) {
|
|
if(!dirname || strcmp(dirname, "")==0 || !rf || n<0) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
/* create directory */
|
|
if(mkdir(dirname, 0777) == -1) {
|
|
if(errno != EEXIST) { /* unknown error */
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
size_t basepathlen = strlen(dirname)+1+1; /* +1 for '/' and +1 for '\0' */
|
|
char *basepath = calloc(basepathlen, sizeof(char));
|
|
if(!basepath) {
|
|
perror("storeFilesInDirectory: calloc");
|
|
return -1;
|
|
}
|
|
strcpy(basepath, dirname);
|
|
strncat(basepath, "/", basepathlen);
|
|
|
|
/* for each file, create and write */
|
|
for(int i=0;i<n;++i) {
|
|
char *filename = calloc(basepathlen + rf[i].pathlen, sizeof(char));
|
|
if(!filename){
|
|
perror("storeFilesInDirectory: calloc");
|
|
free(basepath);
|
|
return -1;
|
|
}
|
|
strcpy(filename, basepath);
|
|
strncat(filename, rf[i].path, basepathlen + rf[i].pathlen);
|
|
|
|
int fdo;
|
|
if((fdo = open(filename, O_WRONLY | O_CREAT, 0666)) == -1) { /* open */
|
|
free(filename);
|
|
free(basepath);
|
|
return -1;
|
|
}
|
|
|
|
if(write(fdo, rf[i].file, rf[i].filelen) == -1) { /* write */
|
|
free(filename);
|
|
free(basepath);
|
|
return -1;
|
|
}
|
|
|
|
if(close(fdo) == -1) { /* close */
|
|
free(filename);
|
|
free(basepath);
|
|
return -1;
|
|
}
|
|
|
|
free(filename);
|
|
}
|
|
|
|
free(basepath);
|
|
return 0;
|
|
}
|
|
|
|
void freeResponse(response_t *res) {
|
|
if(!res)
|
|
return;
|
|
if(res->numfiles>0 && res->rf){
|
|
for(int i=0;i<res->numfiles;++i){
|
|
if(res->rf[i].path)
|
|
free(res->rf[i].path);
|
|
res->rf[i].path = NULL;
|
|
if(res->rf[i].file)
|
|
free(res->rf[i].file);
|
|
res->rf[i].file = NULL;
|
|
}
|
|
free(res->rf);
|
|
}
|
|
return;
|
|
}
|
|
|
|
int isOpen(const char *pathname, const int flags) {
|
|
if(!pathname) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if (openedFiles == NULL || openedFiles->f == NULL || openedFiles->numOfFiles == 0) {
|
|
return 0;
|
|
}
|
|
|
|
files_t *tmp = openedFiles->f;
|
|
while(tmp) {
|
|
if(strcmp(tmp->filename, pathname) == 0 && (tmp->locked || !(flags&O_LOCK)))
|
|
return 1;
|
|
tmp = tmp->next;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int addOpenFile(const char *pathname, const int flags) {
|
|
if(!pathname) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
files_t *new = malloc(sizeof(files_t));
|
|
if(!new) {
|
|
perror("addOpenFile: malloc");
|
|
return -1;
|
|
}
|
|
|
|
size_t len = strlen(pathname)+1;
|
|
new->locked = flags&O_LOCK;
|
|
new->filename = calloc(len, sizeof(char));
|
|
if(!new->filename) {
|
|
perror("addOpenFile: calloc");
|
|
free(new);
|
|
return -1;
|
|
}
|
|
|
|
strncpy(new->filename, pathname, len);
|
|
new->next = NULL;
|
|
|
|
if(openedFiles->f == NULL) {
|
|
openedFiles->f = new;
|
|
openedFiles->numOfFiles = 1;
|
|
return 0;
|
|
}
|
|
|
|
files_t *tail = openedFiles->f;
|
|
while(tail->next) {
|
|
tail = tail->next;
|
|
}
|
|
tail->next = new;
|
|
openedFiles->numOfFiles++;
|
|
return 0;
|
|
}
|
|
|
|
int removeOpenFile(const char *pathname) {
|
|
if(!pathname) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
}
|
|
|
|
if(!openedFiles || !openedFiles->f || openedFiles->numOfFiles == 0) {
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
|
|
files_t *tmp = openedFiles->f;
|
|
|
|
/* the element to remove is the first */
|
|
if(strcmp(tmp->filename, pathname) == 0) {
|
|
openedFiles->f = tmp->next;
|
|
free(tmp->filename);
|
|
free(tmp);
|
|
return 0;
|
|
}
|
|
|
|
files_t *prc = NULL;
|
|
|
|
while(tmp->next) {
|
|
prc = tmp;
|
|
tmp = tmp->next;
|
|
if(strcmp(tmp->filename, pathname) == 0) {
|
|
prc->next = tmp->next;
|
|
free(tmp->filename);
|
|
free(tmp);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* file not found */
|
|
errno = ENOENT;
|
|
return -1;
|
|
}
|
|
|
|
int closeEveryFile() {
|
|
if (openedFiles == NULL)
|
|
return 0;
|
|
|
|
if (openedFiles->numOfFiles > 0 && openedFiles->f != NULL) {
|
|
files_t *tmp = openedFiles->f;
|
|
files_t *prc = NULL;
|
|
while(tmp){
|
|
prc = tmp;
|
|
tmp = tmp->next;
|
|
|
|
if(closeFile(prc->filename) != 0) {
|
|
if(removeOpenFile(prc->filename) != 0) {
|
|
perror("closeEveryFile: removeOpenfile");
|
|
}
|
|
openedFiles->numOfFiles--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(openedFiles->createdAndLocked) {
|
|
free(openedFiles->createdAndLocked);
|
|
openedFiles->createdAndLocked = NULL;
|
|
}
|
|
if(openedFiles->validrDir) {
|
|
free(openedFiles->rDir);
|
|
openedFiles->validrDir = 0;
|
|
openedFiles->rDir = NULL;
|
|
}
|
|
if(openedFiles->validwDir) {
|
|
free(openedFiles->wDir);
|
|
openedFiles->validwDir = 0;
|
|
openedFiles->wDir = NULL;
|
|
}
|
|
|
|
free(openedFiles);
|
|
openedFiles = NULL;
|
|
return 0;
|
|
}
|
|
|
|
int createOpenedFiles() {
|
|
openedFiles = calloc(1, sizeof(*openedFiles));
|
|
if(!openedFiles) {
|
|
perror("createOpenedFiles: calloc");
|
|
return -1;
|
|
}
|
|
openedFiles->f = NULL;
|
|
openedFiles->numOfFiles = 0;
|
|
openedFiles->createdAndLocked = NULL;
|
|
openedFiles->validrDir = 0;
|
|
openedFiles->rDir = NULL;
|
|
openedFiles->validwDir = 0;
|
|
openedFiles->wDir = NULL;
|
|
openedFiles->print = 0;
|
|
openedFiles->out = NULL;
|
|
return 0;
|
|
}
|