242 lines
4.7 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <dirent.h>
#define MAXDATASIZE 1024
#define DATOTEKA 2147483648
#define MAPA 1073741824
#define KONEC 0
typedef struct Data
{
uint32_t size;
uint32_t type;
char name[128];
} Data;
int isDir(const char *path)
{
struct stat path_stat;
stat(path, &path_stat);
return S_ISDIR(path_stat.st_mode);
}
void sendFile(int sockfd, const char *fileName)
{
struct stat st;
stat(fileName, &st);
Data dataS;
dataS.size = st.st_size;
dataS.type = DATOTEKA;
memset(dataS.name, '\0', sizeof(dataS.name));
strcpy(dataS.name, fileName);
if (send(sockfd, &dataS, sizeof(dataS), 0) < 0)
{
perror("send");
return;
}
FILE *ptr = fopen(fileName, "rb");
if (ptr == NULL)
{
perror("File");
return;
}
uint8_t buffer[MAXDATASIZE];
size_t bytesRead = 0;
while (bytesRead < st.st_size)
{
size_t read = fread(buffer, 1, sizeof(buffer), ptr);
if (send(sockfd, buffer, read, 0) < 0)
{
perror("send");
}
bytesRead += read;
}
fclose(ptr);
printf("USPEL\tZBIRKA\t%s\t%d\n", dataS.name, dataS.size);
}
void sendDir(int sockfd, const char *folderName)
{
Data dataToSend;
dataToSend.size = 0;
dataToSend.type = MAPA;
strcpy(dataToSend.name, folderName);
if (send(sockfd, &dataToSend, sizeof(dataToSend), 0) < 0)
{
perror("send");
return;
}
printf("USPEL\tIMENIK\t%s\t%d\n", dataToSend.name, dataToSend.size);
}
void reciveConferm(int sockfd)
{
uint8_t ret;
if ((recv(sockfd, &ret, sizeof(ret), 0)) == -1)
{
perror("recv");
}
}
void sendEnd(int sockfd)
{
Data dataToSend;
dataToSend.size = 0;
dataToSend.type = KONEC;
strcpy(dataToSend.name, "");
if (send(sockfd, &dataToSend, sizeof(dataToSend), 0) < 0)
{
perror("send");
return;
}
}
void sendFullFile(int sockfd, char *input)
{
//nik/nik/nik.txt
char *ptr = strtok(input, "/");
char fileName[128];
memset(fileName, '\0', sizeof(fileName));
while (ptr != NULL)
{
strcat(fileName, ptr);
if (isDir(fileName))
{
sendDir(sockfd, fileName);
strcat(fileName, "/");
}
else
{
sendFile(sockfd, fileName);
}
reciveConferm(sockfd);
ptr = strtok(NULL, "/");
}
}
void sendFullDir(int sockfd, char *input)
{
char fileName[128];
memset(fileName, '\0', sizeof(fileName));
//nik/test
char *ptr = strtok(input, "/");
while (ptr != NULL)
{
strcat(fileName, ptr);
if (isDir(fileName))
{
sendDir(sockfd, fileName);
strcat(fileName, "/");
}
reciveConferm(sockfd);
ptr = strtok(NULL, "/");
}
struct dirent *files;
DIR *dir = opendir(fileName);
if (dir == NULL)
{
printf("Directory cannot be opened!");
return;
}
//nik/test/nik.txt
char srcName[128];
while ((files = readdir(dir)) != NULL)
{
if(strncmp( "..", files->d_name, 2) > -1) continue;
if(strncmp( ".", files->d_name, 1) > -1) continue;
strcpy(srcName, fileName);
strcat(srcName, files->d_name);
if (!isDir(srcName))
{
sendFile(sockfd, srcName);
reciveConferm(sockfd);
}
else
{
sendFullDir(sockfd, srcName);
}
}
closedir(dir);
}
int main(int argc, char *argv[])
{
if (argc != 4)
{
//write(0, "Uporaba: TCPtimec ime vrata datoteka\n\0", 29);
printf("Uporaba: TCPtimec ime vrata datoteka\n");
exit(1);
}
int sockfd; // socekt file descriptor, new file descriptor
struct hostent *he; // pointer to the structure hostent (returned by gethostbyname)
struct sockaddr_in their_addr; // server address
// get the server IP address
if ((he = gethostbyname(argv[1])) == NULL)
{
herror("gethostbyname"); // prints string + value of h_error variable [HOST_NOT_FOUND || NO_ADDRESS or NO_DATA || NO_RECOVERY || TRY_AGAIN]
exit(1);
}
// create socket
if ((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("socket");
exit(1);
}
their_addr.sin_family = AF_INET; // family to Address Family InterNET
their_addr.sin_port = htons(atoi(argv[2])); // get server's port number - should be checked for input errors (not a number, etc.)
their_addr.sin_addr = *((struct in_addr *)he->h_addr); // server's IP address from hostent structure pointed to by he variable...
memset(&(their_addr.sin_zero), '\0', 8); // for conversion between structures only, a trick to ensure pointer casting...
// connect to the server... (no bind necessary as we are connecting to remote host... Kernel will find a free port for us and will bind it to sockfd)
if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr)) == -1)
{
perror("connect");
exit(1);
}
//nik
if (isDir(argv[3]))
{
sendFullDir(sockfd, argv[3]);
}
else
{
sendFullFile(sockfd, argv[3]);
}
sendEnd(sockfd);
// close socket
close(sockfd);
return 0;
}