Skip to content

Instantly share code, notes, and snippets.

@luckyyang
Created July 22, 2012 02:45
Show Gist options
  • Save luckyyang/3158023 to your computer and use it in GitHub Desktop.
Save luckyyang/3158023 to your computer and use it in GitHub Desktop.
myscp
# Jiyang.Liu
# 2012.7.22
src = $(wildcard *.c)
target = $(patsubst %.c, %, $(src))
CC = gcc
LDFLAGS = -Wall -g
all: $(target)
$(target): %: %.c
$(CC) $(LDFLAGS) -o $@ $<
clean:
-rm -f $(target)
distclean: clean
@-rm -f *~ *~~ .*.swp
.PHONY: all clean distclean
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <regex.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
//int stat(const char *path, struct stat *buf);
//int regcomp(regex_t *preg, const char *regex, int cflags);
//int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
#define SERV_IP "127.0.0.1"
#define SERV_PORT 8000
char *parse(char *src, char *delim, char **filename)
{
char *saveptr1, *saveptr2, *token = malloc(100);
char *tmp = malloc(100);
strcpy(token, src);
strcpy(tmp, src);
//get the file name
*filename = strtok_r(token, "/", &saveptr1);
while(tmp){
tmp = strtok_r(NULL, "/", &saveptr1);
if(tmp == NULL)
break;
*filename = tmp;
}
//get the path
src = strtok_r(src, delim, &saveptr2);
tmp = strtok_r(NULL, delim, &saveptr2);
if(tmp != NULL)
src = tmp;
return src;
}
void perr_exit(char *s)
{
perror(s);
exit(1);
}
char *file_or_dir(char *path)
{
struct stat buf;
char *str = NULL;
if(stat(path, &buf) == -1)
str = "File/Directory name invalid, EXIT!";
if(S_ISREG(buf.st_mode))
str = "regular";
if(S_ISDIR(buf.st_mode))
str = "directory";
return str;
}
int main(int argc, char *argv[])
{
int sfd;
struct sockaddr_in serv_addr;
char buf[1024];
int n, fd_rd, fd_wr;
char *src, *des, **filename; //用于存放argv[1]文件名解析的变量
char *src2, *des2, **filename2; //用于存放argv[2]文件名解析的变量
char *tmp = malloc(100);
sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1){
perror("socket error");
exit(1);
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);
if(connect(sfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1){
perror("connect error");
exit(1);
}
des = malloc(100);
src = malloc(100);
filename = malloc(100);
strcpy(src, argv[1]);
des = parse(src, ":", filename); //parse argv[1], des save the path, filename save the filename
des2 = malloc(100);
src2 = malloc(100);
filename2 = malloc(100);
strcpy(src2, argv[2]);
des2 = parse(src2, ":", filename2); //parse argv[2]
if(des2[strlen(des2)-1] != '/'){ //处理argv[2]最后目录名是否有'/',没有则添加
des2[strlen(des2)+1] = '\0';
des2[strlen(des2)] = '/';
}
if(strcmp(des, argv[1]) != 0){ //如果解析argv[1]为服务器文件名,则下面从服务器传文件
strcpy(tmp, *filename);
sprintf(tmp, "%s%s", des2, *filename);
*filename = tmp;
//check if des2/argv[2] is a directory for client to receive file
if(strcmp("directory", file_or_dir(des2)) == 0){ //目录directory
write(sfd, "s_to_c", 7); //tell sever this string is for transfering file from server to client
write(sfd, des, strlen(des)); //将准备拷贝的文件名(des)传给sever
//waiting for server stat the des, if receiving "ok" then can receive the file
while(1){
if((n = read(sfd, buf, 3)) > 0){
buf[n] = '\0';
if(strcmp("ok", buf) == 0){
printf("starting receiving the file...\n");
break;
}else{
printf("%s, exit!\n", buf);
exit(1);
}
}
}
/*打开文件,写;不存在则创建,存在则以截断方式打开*/
if((fd_wr = open(*filename, O_WRONLY|O_CREAT|O_EXCL, 0755)) < 0){
if(errno == EEXIST){
printf("%s exists, will replace it!\n", *filename);
sleep(2);
if((fd_wr = open(*filename, O_WRONLY|O_TRUNC)) < 0)
perr_exit("open fd_rd error");
}
}
printf("\nreceiving...\n\n");
while((n = read(sfd, buf, 1024)) > 0){
write(fd_wr, buf, n);
}
if(n == 0){
printf("received to client completely, location: %s\n", *filename);
close(sfd);
close(fd_wr);
}
}else{
tmp = des2;
tmp[strlen(tmp)-1] = '\0';
printf("%s is not a legal directory name, EXIT!\n", tmp);
exit(1);
}
//否则如果解析argv[1]为客户端文件名,则从客户端向服务器传文件
}else if(strcmp(des, argv[1]) == 0){
if(strcmp("directory", file_or_dir(argv[1])) == 0){ //目录directory
printf("%s must be a filename, can not be a directory\n", *filename);
exit(1);
}else if(strcmp("regular", file_or_dir(argv[1])) == 0){ //文件regular
strcpy(tmp, *filename);
sprintf(*filename, "%s%s", des2, tmp);
printf("des2: %s \n", des2);
printf("filename: %s \n", *filename);
write(sfd, "c_to_s", 7); //tell sever this string is for transfering file from server to client
if((n = read(sfd, buf, 1023)) > 0){
buf[n] = '\0';
if(strcmp("c_to_s_ok", buf) != 0){
printf("transfer 'c_to_s_ok' error\n");
}
}
write(sfd, des2, strlen(des2)); //将准备拷贝的path传给server
if((n = read(sfd, buf, 1023)) > 0){
buf[n] = '\0';
if(strcmp("filename_ok", buf) != 0){
printf("the dir of %s does not exist, EXIT!\n", *filename);
exit(1);
}
}
write(sfd, *filename, strlen(*filename)); //将准备拷贝的文件名传给server
if((n = read(sfd, buf, 1023)) > 0){
buf[n] = '\0';
if(strcmp("ok", buf) == 0){
printf("starting transfering the file...\n");
}
}
/*open and read*/
if((fd_rd = open(argv[1], O_RDONLY)) < 0)
perr_exit("open fd_rd error");
while((n = read(fd_rd, buf, 1024)) > 0){
printf("read %d bytes\n", n);
write(sfd, buf, n);
}
if(n == 0){
printf("transfer to server finished\n");
close(sfd);
close(fd_rd);
}
}else{
printf("%s is not a legal file name, EXIT!\n", argv[1]);
exit(1);
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define SERV_PORT 8000
#define SERV_IP "127.0.0.1"
void perr_exit(char *s)
{
perror(s);
exit(1);
}
char *file_or_dir(char *path)
{
struct stat buf;
char *str = NULL;
if(stat(path, &buf) == -1)
str = "File/Directory name invalid, EXIT!";
if(S_ISREG(buf.st_mode))
str = "regular";
if(S_ISDIR(buf.st_mode))
str = "directory";
return str;
}
int main(int argc, char *argv[])
{
struct sockaddr_in serv_addr;
char buf[1024];
char *tmp = malloc(100);
int n, fd_rd, fd_wr;
char **filename; //用于存放argv[1]文件名解析的变量
int lfd, cfd;
//step 1: socket
//int socket(int domain, int type, int protocol);
if((lfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket error");
exit(1);
}
//step 2: bind
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERV_PORT);
//int inet_pton(int af, const char *src, void *dst);
inet_pton(AF_INET, SERV_IP, &serv_addr.sin_addr.s_addr);
//int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
if(bind(lfd, (struct sockaddr *)&serv_addr, (socklen_t)sizeof(serv_addr)) == -1){
perror("bind error");
exit(1);
}
//step 3: listen
if(listen(lfd, 20) == -1){
perror("listen error");
exit(1);
}
printf("Accepting connections...\n");
filename = malloc(100);
while(1){
//step 4: accept
//int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
if((cfd = accept(lfd, NULL, NULL)) == -1){
perror("accept error");
exit(1);
}
while(1){
//step 5: read
if((n = read(cfd, buf, 1023)) < 0)
perr_exit("read error");
else if(n == 0){
printf("write/client end closed\n");
break;
}else{
buf[n] = '\0';
if(strcmp("s_to_c", buf) == 0){ //require server to send file to client
if((n = read(cfd, buf, 1023)) < 0) //first read the file name and stat whether the file exists
perr_exit("read error");
buf[n] = '\0';
*filename = buf;
//add "." into the head of the path(*filename) for server to open
if(*filename[0] != '.' && *filename[0] != '/'){
strcpy(tmp, *filename);
sprintf(*filename, "%s%s", ".", tmp);
}
//printf("filename:%s\n", *filename);
//server stat whether *filename is illegal
if(strcmp("regular", file_or_dir(*filename)) == 0){ //文件regular
if((n = write(cfd, "ok", 3)) < 0) //tell client "ok" to send file
perr_exit("write 'ok' error");
/*打开文件,写*/
if((fd_rd = open(*filename, O_RDONLY)) < 0)
perr_exit("open fd_rd error");
printf("Starting to transfering...\n");
while((n = read(fd_rd, buf, 1024)) > 0){
write(cfd, buf, n);
}
if(n == 0){
printf("transfer to client finished\n");
close(cfd);
close(fd_rd);
break;
}
}else
printf("%s is not a legal file name, EXIT!\n", *filename);
}
//require server to reveive file from client
if(strcmp("c_to_s", buf) == 0){
if((n = write(cfd, "c_to_s_ok", strlen("c_to_s_ok"))) < 0)
perr_exit("write 'c_to_s_ok' error");
if((n = read(cfd, buf, 1023)) < 0) //first read the file name from client
perr_exit("read error");
buf[n] = '\0';
*filename = buf;
printf("filename = %s\n", *filename);
//add "." into the head of the path(*filename) for server to open
if(*filename[0] != '.' && *filename[0] != '/'){
char *tmp = malloc(100);
strcpy(tmp, *filename);
sprintf(*filename, "%s%s", ".", tmp);
tmp = *filename;
}
printf("filename = %s\n", *filename);
//server判断*filename是文件还是目录(stat)
if(strcmp("directory", file_or_dir(*filename)) == 0){ //目录directory
if((n = write(cfd, "filename_ok", strlen("filename_ok"))) < 0) //tell client "ok" to accept the file
perr_exit("write 'filename_ok' error");
if((n = read(cfd, buf, 1023)) < 0) //first read the file name from client
perr_exit("read error");
buf[n] = '\0';
*filename = buf;
//add "." into the head of the path(*filename) for server to open
if(*filename[0] != '.'){
char *tmp = malloc(100);
strcpy(tmp, *filename);
sprintf(*filename, "%s%s", ".", tmp);
}
if((n = write(cfd, "ok", 3)) < 0) //tell client "ok" to accept the file
perr_exit("write 'ok' error");
/*打开文件,写*/
if((fd_wr = open(*filename, O_WRONLY|O_CREAT|O_EXCL, 0755)) < 0){
if(errno == EEXIST){
printf("%s exists, will replace it!\n", *filename);
sleep(2);
printf("\nreceiving...\n\n");
if((fd_wr = open(*filename, O_WRONLY|O_TRUNC)) < 0)
perr_exit("open fd_rd error");
}
}
while((n = read(cfd, buf, 1024)) > 0){
write(fd_wr, buf, n);
//printf("reveived %d bytes\n", n);
}
if(n == 0){
//printf("transfer to server finished, location: %s\n", *filename);
printf("transfer to server finished\n");
close(cfd);
close(fd_wr);
break;
}
}else
printf("%s is not a legal directory name, EXIT!\n", tmp);
}
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment