diff options
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/afcclient.c | 183 | 
1 files changed, 142 insertions, 41 deletions
| diff --git a/tools/afcclient.c b/tools/afcclient.c index adfb1ba..1cd6858 100644 --- a/tools/afcclient.c +++ b/tools/afcclient.c | |||
| @@ -91,6 +91,16 @@ static idevice_subscription_context_t context = NULL; | |||
| 91 | static char* curdir = NULL; | 91 | static char* curdir = NULL; | 
| 92 | static size_t curdir_len = 0; | 92 | static size_t curdir_len = 0; | 
| 93 | 93 | ||
| 94 | static int file_exists(const char* path) | ||
| 95 | { | ||
| 96 | struct stat tst; | ||
| 97 | #ifdef WIN32 | ||
| 98 | return (stat(path, &tst) == 0); | ||
| 99 | #else | ||
| 100 | return (lstat(path, &tst) == 0); | ||
| 101 | #endif | ||
| 102 | } | ||
| 103 | |||
| 94 | static int is_directory(const char* path) | 104 | static int is_directory(const char* path) | 
| 95 | { | 105 | { | 
| 96 | struct stat tst; | 106 | struct stat tst; | 
| @@ -686,7 +696,7 @@ static void handle_remove(afc_client_t afc, int argc, char** argv) | |||
| 686 | } | 696 | } | 
| 687 | } | 697 | } | 
| 688 | 698 | ||
| 689 | static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint64_t file_size) | 699 | static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint64_t file_size, uint8_t force_overwrite) | 
| 690 | { | 700 | { | 
| 691 | uint64_t fh = 0; | 701 | uint64_t fh = 0; | 
| 692 | afc_error_t err = afc_file_open(afc, srcpath, AFC_FOPEN_RDONLY, &fh); | 702 | afc_error_t err = afc_file_open(afc, srcpath, AFC_FOPEN_RDONLY, &fh); | 
| @@ -694,6 +704,10 @@ static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char | |||
| 694 | printf("Error: Failed to open file '%s': %s (%d)\n", srcpath, afc_strerror(err), err); | 704 | printf("Error: Failed to open file '%s': %s (%d)\n", srcpath, afc_strerror(err), err); | 
| 695 | return 0; | 705 | return 0; | 
| 696 | } | 706 | } | 
| 707 | if (file_exists(dstpath) && !force_overwrite) { | ||
| 708 | printf("Error: Failed to overwrite existing file without '-f' option: %s\n", dstpath); | ||
| 709 | return 0; | ||
| 710 | } | ||
| 697 | FILE *f = fopen(dstpath, "wb"); | 711 | FILE *f = fopen(dstpath, "wb"); | 
| 698 | if (!f) { | 712 | if (!f) { | 
| 699 | printf("Error: Failed to open local file '%s': %s\n", dstpath, strerror(errno)); | 713 | printf("Error: Failed to open local file '%s': %s\n", dstpath, strerror(errno)); | 
| @@ -757,7 +771,7 @@ static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char | |||
| 757 | return succeed; | 771 | return succeed; | 
| 758 | } | 772 | } | 
| 759 | 773 | ||
| 760 | static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath) | 774 | static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite, uint8_t recursive_get) | 
| 761 | { | 775 | { | 
| 762 | char **info = NULL; | 776 | char **info = NULL; | 
| 763 | uint64_t file_size = 0; | 777 | uint64_t file_size = 0; | 
| @@ -784,6 +798,10 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 784 | } | 798 | } | 
| 785 | uint8_t succeed = 1; | 799 | uint8_t succeed = 1; | 
| 786 | if (is_dir) { | 800 | if (is_dir) { | 
| 801 | if (!recursive_get) { | ||
| 802 | printf("Error: Failed to get a directory without '-r' option: %s\n", srcpath); | ||
| 803 | return 0; | ||
| 804 | } | ||
| 787 | char **entries = NULL; | 805 | char **entries = NULL; | 
| 788 | err = afc_read_directory(afc, srcpath, &entries); | 806 | err = afc_read_directory(afc, srcpath, &entries); | 
| 789 | if (err != AFC_E_SUCCESS) { | 807 | if (err != AFC_E_SUCCESS) { | 
| @@ -792,9 +810,15 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 792 | } | 810 | } | 
| 793 | char **p = entries; | 811 | char **p = entries; | 
| 794 | size_t srcpath_len = strlen(srcpath); | 812 | size_t srcpath_len = strlen(srcpath); | 
| 795 | int srcpath_is_root = strcmp(srcpath, "/") == 0; | 813 | uint8_t srcpath_is_root = strcmp(srcpath, "/") == 0; | 
| 796 | if (!is_directory(dstpath) && mkdir(dstpath, 0777) != 0) { | 814 | // if directory exists, check force_overwrite flag | 
| 797 | printf("Error: Failed to create folder '%s': %s\n", dstpath, strerror(errno)); | 815 | if (is_directory(dstpath)) { | 
| 816 | if (!force_overwrite) { | ||
| 817 | printf("Error: Failed to write into existing directory without '-f': %s\n", dstpath); | ||
| 818 | return 0; | ||
| 819 | } | ||
| 820 | } else if (mkdir(dstpath, 0777) != 0) { | ||
| 821 | printf("Error: Failed to create directory '%s': %s\n", dstpath, strerror(errno)); | ||
| 798 | afc_dictionary_free(entries); | 822 | afc_dictionary_free(entries); | 
| 799 | return 0; | 823 | return 0; | 
| 800 | } | 824 | } | 
| @@ -803,17 +827,22 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 803 | p++; | 827 | p++; | 
| 804 | continue; | 828 | continue; | 
| 805 | } | 829 | } | 
| 806 | size_t len = srcpath_len + 1 + strlen(*p) + 1; | 830 | size_t len = srcpath_is_root ? strlen(*p) + 1 : srcpath_len + 1 + strlen(*p) + 1; | 
| 807 | char *testpath = (char *) malloc(len); | 831 | char *testpath = (char *) malloc(len); | 
| 808 | if (srcpath_is_root) { | 832 | if (srcpath_is_root) { | 
| 809 | snprintf(testpath, len, "/%s", *p); | 833 | snprintf(testpath, len, "/%s", *p); | 
| 810 | } else { | 834 | } else { | 
| 811 | snprintf(testpath, len, "%s/%s", srcpath, *p); | 835 | snprintf(testpath, len, "%s/%s", srcpath, *p); | 
| 812 | } | 836 | } | 
| 813 | size_t dst_len = strlen(dstpath) + 1 + strlen(*p) + 1; | 837 | uint8_t dst_is_root = strcmp(srcpath, "/") == 0; | 
| 838 | size_t dst_len = dst_is_root ? strlen(*p) + 1 : strlen(dstpath) + 1 + strlen(*p) + 1; | ||
| 814 | char *newdst = (char *) malloc(dst_len); | 839 | char *newdst = (char *) malloc(dst_len); | 
| 815 | snprintf(newdst, dst_len, "%s/%s", dstpath, *p); | 840 | if (dst_is_root) { | 
| 816 | if (!get_file(afc, testpath, newdst)) { | 841 | snprintf(newdst, dst_len, "/%s", *p); | 
| 842 | } else { | ||
| 843 | snprintf(newdst, dst_len, "%s/%s", dstpath, *p); | ||
| 844 | } | ||
| 845 | if (!get_file(afc, testpath, newdst, force_overwrite, recursive_get)) { | ||
| 817 | succeed = 0; | 846 | succeed = 0; | 
| 818 | break; | 847 | break; | 
| 819 | } | 848 | } | 
| @@ -823,21 +852,38 @@ static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 823 | } | 852 | } | 
| 824 | afc_dictionary_free(entries); | 853 | afc_dictionary_free(entries); | 
| 825 | } else { | 854 | } else { | 
| 826 | succeed = get_single_file(afc, srcpath, dstpath, file_size); | 855 | succeed = get_single_file(afc, srcpath, dstpath, file_size, force_overwrite); | 
| 827 | } | 856 | } | 
| 828 | return succeed; | 857 | return succeed; | 
| 829 | } | 858 | } | 
| 830 | 859 | ||
| 831 | static void handle_get(afc_client_t afc, int argc, char **argv) | 860 | static void handle_get(afc_client_t afc, int argc, char **argv) | 
| 832 | { | 861 | { | 
| 833 | if (argc < 1 || argc > 2) { | 862 | if (argc < 1) { | 
| 834 | printf("Error: Invalid number of arguments\n"); | 863 | printf("Error: Invalid number of arguments\n"); | 
| 835 | return; | 864 | return; | 
| 836 | } | 865 | } | 
| 866 | uint8_t force_overwrite = 0, recursive_get = 0; | ||
| 837 | char *srcpath = NULL; | 867 | char *srcpath = NULL; | 
| 838 | char *dstpath = NULL; | 868 | char *dstpath = NULL; | 
| 839 | if (argc == 1) { | 869 | int i = 0; | 
| 840 | char *tmp = strdup(argv[0]); | 870 | for ( ; i < argc; i++) { | 
| 871 | if (!strcmp(argv[i], "--")) { | ||
| 872 | i++; | ||
| 873 | break; | ||
| 874 | } else if (!strcmp(argv[i], "-r")) { | ||
| 875 | recursive_get = 1; | ||
| 876 | } else if (!strcmp(argv[i], "-f")) { | ||
| 877 | force_overwrite = 1; | ||
| 878 | } else if (!strcmp(argv[i], "-rf") || !strcmp(argv[i], "-fr")) { | ||
| 879 | recursive_get = 1; | ||
| 880 | force_overwrite = 1; | ||
| 881 | } else { | ||
| 882 | break; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | if (argc - i == 1) { | ||
| 886 | char *tmp = strdup(argv[i]); | ||
| 841 | size_t src_len = strlen(tmp); | 887 | size_t src_len = strlen(tmp); | 
| 842 | if (src_len > 1 && tmp[src_len - 1] == '/') { | 888 | if (src_len > 1 && tmp[src_len - 1] == '/') { | 
| 843 | tmp[src_len - 1] = '\0'; | 889 | tmp[src_len - 1] = '\0'; | 
| @@ -845,14 +891,14 @@ static void handle_get(afc_client_t afc, int argc, char **argv) | |||
| 845 | srcpath = get_absolute_path(tmp); | 891 | srcpath = get_absolute_path(tmp); | 
| 846 | dstpath = strdup(path_get_basename(tmp)); | 892 | dstpath = strdup(path_get_basename(tmp)); | 
| 847 | free(tmp); | 893 | free(tmp); | 
| 848 | } else { | 894 | } else if (argc - i == 2) { | 
| 849 | char *tmp = strdup(argv[0]); | 895 | char *tmp = strdup(argv[i]); | 
| 850 | size_t src_len = strlen(tmp); | 896 | size_t src_len = strlen(tmp); | 
| 851 | if (src_len > 1 && tmp[src_len - 1] == '/') { | 897 | if (src_len > 1 && tmp[src_len - 1] == '/') { | 
| 852 | tmp[src_len - 1] = '\0'; | 898 | tmp[src_len - 1] = '\0'; | 
| 853 | } | 899 | } | 
| 854 | srcpath = get_absolute_path(tmp); | 900 | srcpath = get_absolute_path(tmp); | 
| 855 | dstpath = strdup(argv[1]); | 901 | dstpath = strdup(argv[i + 1]); | 
| 856 | size_t dst_len = strlen(dstpath); | 902 | size_t dst_len = strlen(dstpath); | 
| 857 | if (dst_len > 1 && dstpath[dst_len - 1] == '/') { | 903 | if (dst_len > 1 && dstpath[dst_len - 1] == '/') { | 
| 858 | dstpath[dst_len - 1] = '\0'; | 904 | dstpath[dst_len - 1] = '\0'; | 
| @@ -863,23 +909,38 @@ static void handle_get(afc_client_t afc, int argc, char **argv) | |||
| 863 | // target is a directory, put file under this target | 909 | // target is a directory, put file under this target | 
| 864 | if (is_directory(dstpath)) { | 910 | if (is_directory(dstpath)) { | 
| 865 | const char *basen = path_get_basename(argv[0]); | 911 | const char *basen = path_get_basename(argv[0]); | 
| 866 | size_t len = strlen(dstpath) + 1 + strlen(basen) + 1; | 912 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; | 
| 913 | size_t len = dst_is_root ? (strlen(basen) + 1) : (strlen(dstpath) + 1 + strlen(basen) + 1); | ||
| 867 | char *newdst = (char *) malloc(len); | 914 | char *newdst = (char *) malloc(len); | 
| 868 | snprintf(newdst, len, "%s/%s", dstpath, basen); | 915 | if (dst_is_root) { | 
| 869 | get_file(afc, srcpath, newdst); | 916 | snprintf(newdst, len, "/%s", basen); | 
| 917 | } else { | ||
| 918 | snprintf(newdst, len, "%s/%s", dstpath, basen); | ||
| 919 | } | ||
| 920 | get_file(afc, srcpath, newdst, force_overwrite, recursive_get); | ||
| 870 | free(srcpath); | 921 | free(srcpath); | 
| 871 | free(newdst); | 922 | free(newdst); | 
| 872 | free(dstpath); | 923 | free(dstpath); | 
| 873 | } else { | 924 | } else { | 
| 874 | // target is not a dir or does not exist, just try to create or rewrite it | 925 | // target is not a dir or does not exist, just try to create or rewrite it | 
| 875 | get_file(afc, srcpath, dstpath); | 926 | get_file(afc, srcpath, dstpath, force_overwrite, recursive_get); | 
| 876 | free(srcpath); | 927 | free(srcpath); | 
| 877 | free(dstpath); | 928 | free(dstpath); | 
| 878 | } | 929 | } | 
| 879 | } | 930 | } | 
| 880 | 931 | ||
| 881 | static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath) | 932 | static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite) | 
| 882 | { | 933 | { | 
| 934 | char **info = NULL; | ||
| 935 | afc_error_t ret = afc_get_file_info(afc, dstpath, &info); | ||
| 936 | // file exists, only overwrite with '-f' option was set | ||
| 937 | if (ret == AFC_E_SUCCESS && info) { | ||
| 938 | afc_dictionary_free(info); | ||
| 939 | if (!force_overwrite) { | ||
| 940 | printf("Error: Failed to write into existing file without '-f' option: %s\n", dstpath); | ||
| 941 | return 0; | ||
| 942 | } | ||
| 943 | } | ||
| 883 | FILE *f = fopen(srcpath, "rb"); | 944 | FILE *f = fopen(srcpath, "rb"); | 
| 884 | if (!f) { | 945 | if (!f) { | 
| 885 | printf("Error: Failed to open local file '%s': %s\n", srcpath, strerror(errno)); | 946 | printf("Error: Failed to open local file '%s': %s\n", srcpath, strerror(errno)); | 
| @@ -949,20 +1010,27 @@ static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char | |||
| 949 | return succeed; | 1010 | return succeed; | 
| 950 | } | 1011 | } | 
| 951 | 1012 | ||
| 952 | static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpath) | 1013 | static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint8_t force_overwrite, uint8_t recursive_put) | 
| 953 | { | 1014 | { | 
| 954 | if (is_directory(srcpath)) { | 1015 | if (is_directory(srcpath)) { | 
| 1016 | if (!recursive_put) { | ||
| 1017 | printf("Error: Failed to put directory without '-r' option: %s\n", srcpath); | ||
| 1018 | return 0; | ||
| 1019 | } | ||
| 955 | char **info = NULL; | 1020 | char **info = NULL; | 
| 956 | afc_error_t err = afc_get_file_info(afc, dstpath, &info); | 1021 | afc_error_t err = afc_get_file_info(afc, dstpath, &info); | 
| 957 | //create if target directory does not exist | 1022 | //create if target directory does not exist | 
| 1023 | afc_dictionary_free(info); | ||
| 958 | if (err == AFC_E_OBJECT_NOT_FOUND) { | 1024 | if (err == AFC_E_OBJECT_NOT_FOUND) { | 
| 959 | err = afc_make_directory(afc, dstpath); | 1025 | err = afc_make_directory(afc, dstpath); | 
| 960 | if (err != AFC_E_SUCCESS) { | 1026 | if (err != AFC_E_SUCCESS) { | 
| 961 | printf("Error: Failed to create directory '%s': %s (%d)\n", dstpath, afc_strerror(err), err); | 1027 | printf("Error: Failed to create directory '%s': %s (%d)\n", dstpath, afc_strerror(err), err); | 
| 962 | return 0; | 1028 | return 0; | 
| 963 | } | 1029 | } | 
| 1030 | } else if (!force_overwrite) { | ||
| 1031 | printf("Error: Failed to put existing directory without '-f' option: %s\n", dstpath); | ||
| 1032 | return 0; | ||
| 964 | } | 1033 | } | 
| 965 | afc_dictionary_free(info); | ||
| 966 | afc_get_file_info(afc, dstpath, &info); | 1034 | afc_get_file_info(afc, dstpath, &info); | 
| 967 | uint8_t is_dir = 0; | 1035 | uint8_t is_dir = 0; | 
| 968 | if (info) { | 1036 | if (info) { | 
| @@ -978,7 +1046,7 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 978 | afc_dictionary_free(info); | 1046 | afc_dictionary_free(info); | 
| 979 | } | 1047 | } | 
| 980 | if (!is_dir) { | 1048 | if (!is_dir) { | 
| 981 | printf("Error: Failed to create or access directory: '%s'", dstpath); | 1049 | printf("Error: Failed to create or access directory: '%s'\n", dstpath); | 
| 982 | return 0; | 1050 | return 0; | 
| 983 | } | 1051 | } | 
| 984 | 1052 | ||
| @@ -992,10 +1060,15 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 992 | } | 1060 | } | 
| 993 | char *fpath = string_build_path(srcpath, ep->d_name, NULL); | 1061 | char *fpath = string_build_path(srcpath, ep->d_name, NULL); | 
| 994 | if (fpath) { | 1062 | if (fpath) { | 
| 995 | size_t len = strlen(srcpath) + 1 + strlen(ep->d_name) + 1; | 1063 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; | 
| 1064 | size_t len = dst_is_root ? strlen(ep->d_name) + 1 : strlen(dstpath) + 1 + strlen(ep->d_name) + 1; | ||
| 996 | char *newdst = (char *) malloc(len); | 1065 | char *newdst = (char *) malloc(len); | 
| 997 | snprintf(newdst, len, "%s/%s", dstpath, ep->d_name); | 1066 | if (dst_is_root) { | 
| 998 | if (!put_file(afc, fpath, newdst)) { | 1067 | snprintf(newdst, len, "/%s", ep->d_name); | 
| 1068 | } else { | ||
| 1069 | snprintf(newdst, len, "%s/%s", dstpath, ep->d_name); | ||
| 1070 | } | ||
| 1071 | if (!put_file(afc, fpath, newdst, force_overwrite, recursive_put)) { | ||
| 999 | free(newdst); | 1072 | free(newdst); | 
| 1000 | free(fpath); | 1073 | free(fpath); | 
| 1001 | return 0; | 1074 | return 0; | 
| @@ -1006,44 +1079,67 @@ static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpa | |||
| 1006 | } | 1079 | } | 
| 1007 | closedir(cur_dir); | 1080 | closedir(cur_dir); | 
| 1008 | } else { | 1081 | } else { | 
| 1009 | printf("Error: Failed to visit directory: '%s': %s", srcpath, strerror(errno)); | 1082 | printf("Error: Failed to visit directory: '%s': %s\n", srcpath, strerror(errno)); | 
| 1010 | return 0; | 1083 | return 0; | 
| 1011 | } | 1084 | } | 
| 1012 | } else { | 1085 | } else { | 
| 1013 | return put_single_file(afc, srcpath, dstpath); | 1086 | return put_single_file(afc, srcpath, dstpath, force_overwrite); | 
| 1014 | } | 1087 | } | 
| 1015 | return 1; | 1088 | return 1; | 
| 1016 | } | 1089 | } | 
| 1017 | 1090 | ||
| 1018 | static void handle_put(afc_client_t afc, int argc, char **argv) | 1091 | static void handle_put(afc_client_t afc, int argc, char **argv) | 
| 1019 | { | 1092 | { | 
| 1020 | if (argc < 1 || argc > 2) { | 1093 | if (argc < 1) { | 
| 1021 | printf("Error: Invalid number of arguments\n"); | 1094 | printf("Error: Invalid number of arguments\n"); | 
| 1022 | return; | 1095 | return; | 
| 1023 | } | 1096 | } | 
| 1024 | 1097 | int i = 0; | |
| 1025 | char *srcpath = strdup(argv[0]); | 1098 | uint8_t force_overwrite = 0, recursive_put = 0; | 
| 1099 | for ( ; i < argc; i++) { | ||
| 1100 | if (!strcmp(argv[i], "--")) { | ||
| 1101 | i++; | ||
| 1102 | break; | ||
| 1103 | } else if (!strcmp(argv[i], "-r")) { | ||
| 1104 | recursive_put = 1; | ||
| 1105 | } else if (!strcmp(argv[i], "-f")) { | ||
| 1106 | force_overwrite = 1; | ||
| 1107 | } else if (!strcmp(argv[i], "-rf") || !strcmp(argv[i], "-fr")) { | ||
| 1108 | recursive_put = 1; | ||
| 1109 | force_overwrite = 1; | ||
| 1110 | } else { | ||
| 1111 | break; | ||
| 1112 | } | ||
| 1113 | } | ||
| 1114 | if (i >= argc) { | ||
| 1115 | printf("Error: Invalid number of arguments\n"); | ||
| 1116 | return; | ||
| 1117 | } | ||
| 1118 | char *srcpath = strdup(argv[i]); | ||
| 1026 | size_t src_len = strlen(srcpath); | 1119 | size_t src_len = strlen(srcpath); | 
| 1027 | if (src_len > 1 && srcpath[src_len - 1] == '/') { | 1120 | if (src_len > 1 && srcpath[src_len - 1] == '/') { | 
| 1028 | srcpath[src_len - 1] = '\0'; | 1121 | srcpath[src_len - 1] = '\0'; | 
| 1029 | } | 1122 | } | 
| 1030 | char *dstpath = NULL; | 1123 | char *dstpath = NULL; | 
| 1031 | if (argc == 1) { | 1124 | if (argc - i == 1) { | 
| 1032 | dstpath = get_absolute_path(path_get_basename(srcpath)); | 1125 | dstpath = get_absolute_path(path_get_basename(srcpath)); | 
| 1033 | } else { | 1126 | } else if (argc - i == 2) { | 
| 1034 | char *tmp = strdup(argv[1]); | 1127 | char *tmp = strdup(argv[i + 1]); | 
| 1035 | size_t dst_len = strlen(tmp); | 1128 | size_t dst_len = strlen(tmp); | 
| 1036 | if (dst_len > 1 && tmp[dst_len - 1] == '/') { | 1129 | if (dst_len > 1 && tmp[dst_len - 1] == '/') { | 
| 1037 | tmp[dst_len - 1] = '\0'; | 1130 | tmp[dst_len - 1] = '\0'; | 
| 1038 | } | 1131 | } | 
| 1039 | dstpath = get_absolute_path(tmp); | 1132 | dstpath = get_absolute_path(tmp); | 
| 1040 | free(tmp); | 1133 | free(tmp); | 
| 1134 | } else { | ||
| 1135 | printf("Error: Invalid number of arguments\n"); | ||
| 1136 | return; | ||
| 1041 | } | 1137 | } | 
| 1042 | char **info = NULL; | 1138 | char **info = NULL; | 
| 1043 | afc_error_t err = afc_get_file_info(afc, dstpath, &info); | 1139 | afc_error_t err = afc_get_file_info(afc, dstpath, &info); | 
| 1044 | // target does not exist, put directly | 1140 | // target does not exist, put directly | 
| 1045 | if (err == AFC_E_OBJECT_NOT_FOUND) { | 1141 | if (err == AFC_E_OBJECT_NOT_FOUND) { | 
| 1046 | put_file(afc, srcpath, dstpath); | 1142 | put_file(afc, srcpath, dstpath, force_overwrite, recursive_put); | 
| 1047 | free(srcpath); | 1143 | free(srcpath); | 
| 1048 | free(dstpath); | 1144 | free(dstpath); | 
| 1049 | } else { | 1145 | } else { | 
| @@ -1060,19 +1156,24 @@ static void handle_put(afc_client_t afc, int argc, char **argv) | |||
| 1060 | } | 1156 | } | 
| 1061 | afc_dictionary_free(info); | 1157 | afc_dictionary_free(info); | 
| 1062 | } | 1158 | } | 
| 1063 | // target is a dir, put under this target | 1159 | // target is a directory, try to put under this directory | 
| 1064 | if (is_dir) { | 1160 | if (is_dir) { | 
| 1065 | const char *basen = path_get_basename(srcpath); | 1161 | const char *basen = path_get_basename(srcpath); | 
| 1066 | size_t len = strlen(dstpath) + 1 + strlen(basen) + 1; | 1162 | uint8_t dst_is_root = strcmp(dstpath, "/") == 0; | 
| 1163 | size_t len = dst_is_root ? strlen(basen) + 1 : strlen(dstpath) + 1 + strlen(basen) + 1; | ||
| 1067 | char *newdst = (char *) malloc(len); | 1164 | char *newdst = (char *) malloc(len); | 
| 1068 | snprintf(newdst, len, "%s/%s", dstpath, basen); | 1165 | if (dst_is_root) { | 
| 1166 | snprintf(newdst, len, "/%s", basen); | ||
| 1167 | } else { | ||
| 1168 | snprintf(newdst, len, "%s/%s", dstpath, basen); | ||
| 1169 | } | ||
| 1069 | free(dstpath); | 1170 | free(dstpath); | 
| 1070 | dstpath = get_absolute_path(newdst); | 1171 | dstpath = get_absolute_path(newdst); | 
| 1071 | free(newdst); | 1172 | free(newdst); | 
| 1072 | put_file(afc, srcpath, dstpath); | 1173 | put_file(afc, srcpath, dstpath, force_overwrite, recursive_put); | 
| 1073 | } else { | 1174 | } else { | 
| 1074 | //target is common file, rewrite it | 1175 | //target is common file, rewrite it | 
| 1075 | put_file(afc, srcpath, dstpath); | 1176 | put_file(afc, srcpath, dstpath, force_overwrite, recursive_put); | 
| 1076 | } | 1177 | } | 
| 1077 | free(srcpath); | 1178 | free(srcpath); | 
| 1078 | free(dstpath); | 1179 | free(dstpath); | 
