summaryrefslogtreecommitdiffstats
path: root/tools/afcclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/afcclient.c')
-rw-r--r--tools/afcclient.c183
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;
91static char* curdir = NULL; 91static char* curdir = NULL;
92static size_t curdir_len = 0; 92static size_t curdir_len = 0;
93 93
94static 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
94static int is_directory(const char* path) 104static 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
689static uint8_t get_single_file(afc_client_t afc, const char *srcpath, const char *dstpath, uint64_t file_size) 699static 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
760static uint8_t get_file(afc_client_t afc, const char *srcpath, const char *dstpath) 774static 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
831static void handle_get(afc_client_t afc, int argc, char **argv) 860static 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
881static uint8_t put_single_file(afc_client_t afc, const char *srcpath, const char *dstpath) 932static 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
952static uint8_t put_file(afc_client_t afc, const char *srcpath, const char *dstpath) 1013static 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
1018static void handle_put(afc_client_t afc, int argc, char **argv) 1091static 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);