Created
July 22, 2012 02:45
-
-
Save luckyyang/3158023 to your computer and use it in GitHub Desktop.
myscp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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