void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) { enum { SRC_BUF_SIZE = 45, /* This *MUST* be a multiple of 3 */ DST_BUF_SIZE = 4 * ((SRC_BUF_SIZE + 2) / 3), }; #define src_buf text char src[SRC_BUF_SIZE]; FILE *fp = fp; ssize_t len = len; char dst_buf[DST_BUF_SIZE + 1]; if (fname) { fp = (NOT_LONE_DASH(fname)) ? xfopen_for_read(fname) : (FILE *)text; src_buf = src; } else if (text) { // though we do not call uuencode(NULL, NULL) explicitly // still we do not want to break things suddenly len = strlen(text); } else return; while (1) { size_t size; if (fname) { size = fread((char *)src_buf, 1, SRC_BUF_SIZE, fp); if ((ssize_t)size < 0) bb_perror_msg_and_die(bb_msg_read_error); } else { size = len; if (len > SRC_BUF_SIZE) size = SRC_BUF_SIZE; } if (!size) break; // encode the buffer we just read in bb_uuencode(dst_buf, src_buf, size, bb_uuenc_tbl_base64); if (fname) { printf("%s\n", eol); } else { src_buf += size; len -= size; } fwrite(dst_buf, 1, 4 * ((size + 2) / 3), stdout); } if (fname && NOT_LONE_DASH(fname)) fclose(fp); #undef src_buf }
static int ftp_send(ftp_host_info_t *server, FILE *control_stream, const char *server_path, char *local_path) { struct stat sbuf; char buf[512]; int fd_data; int fd_local; int response; /* Connect to the data socket */ if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { ftp_die("PASV", buf); } fd_data = xconnect_ftpdata(server, buf); /* get the local file */ fd_local = STDIN_FILENO; if (NOT_LONE_DASH(local_path)) { fd_local = xopen(local_path, O_RDONLY, 0666); fstat(fd_local, &sbuf); sprintf(buf, "ALLO %lu", (long unsigned int)sbuf.st_size); response = ftpcmd(buf, NULL, control_stream, buf); switch (response) { case 200: case 202: break; default: close(fd_local); ftp_die("ALLO", buf); break; } } response = ftpcmd("STOR", server_path, control_stream, buf); switch (response) { case 125: case 150: break; default: close(fd_local); ftp_die("STOR", buf); } /* transfer the file */ if (bb_copyfd_eof(fd_local, fd_data) == -1) { exit(EXIT_FAILURE); } /* close it all down */ close(fd_data); if (ftpcmd(NULL, NULL, control_stream, buf) != 226) { ftp_die("close", buf); } ftpcmd("QUIT", NULL, control_stream, buf); return EXIT_SUCCESS; }
int crontab_main(int argc UNUSED_PARAM, char **argv) { const struct passwd *pas; const char *crontab_dir = CRONTABS; char *tmp_fname; char *new_fname; char *user_name; /* -u USER */ int fd; int src_fd; int opt_ler; /* file [opts] Replace crontab from file * - [opts] Replace crontab from stdin * -u user User * -c dir Crontab directory * -l List crontab for user * -e Edit crontab for user * -r Delete crontab for user * bbox also supports -d == -r, but most other crontab * implementations do not. Deprecated. */ enum { OPT_u = (1 << 0), OPT_c = (1 << 1), OPT_l = (1 << 2), OPT_e = (1 << 3), OPT_r = (1 << 4), OPT_ler = OPT_l + OPT_e + OPT_r, }; opt_complementary = "?1:dr"; /* max one argument; -d implies -r */ opt_ler = getopt32(argv, "u:c:lerd", &user_name, &crontab_dir); argv += optind; if (sanitize_env_if_suid()) { /* Clears dangerous stuff, sets PATH */ /* run by non-root? */ if (opt_ler & (OPT_u|OPT_c)) bb_error_msg_and_die("only root can use -c or -u"); } if (opt_ler & OPT_u) { pas = getpwnam(user_name); if (!pas) bb_error_msg_and_die("user %s is not known", user_name); } else { /* XXX: xgetpwuid */ uid_t my_uid = getuid(); pas = getpwuid(my_uid); if (!pas) bb_perror_msg_and_die("unknown uid %d", (int)my_uid); } #define user_name DONT_USE_ME_BEYOND_THIS_POINT /* From now on, keep only -l, -e, -r bits */ opt_ler &= OPT_ler; if ((opt_ler - 1) & opt_ler) /* more than one bit set? */ bb_show_usage(); /* Read replacement file under user's UID/GID/group vector */ src_fd = STDIN_FILENO; if (!opt_ler) { /* Replace? */ if (!argv[0]) bb_show_usage(); if (NOT_LONE_DASH(argv[0])) { src_fd = open_as_user(pas, argv[0]); if (src_fd < 0) bb_error_msg_and_die("user %s cannot read %s", pas->pw_name, argv[0]); } } /* cd to our crontab directory */ xchdir(crontab_dir); tmp_fname = NULL; /* Handle requested operation */ switch (opt_ler) { default: /* case OPT_r: Delete */ unlink(pas->pw_name); break; case OPT_l: /* List */ { char *args[2] = { pas->pw_name, NULL }; return bb_cat(args); /* list exits, * the rest go play with cron update file */ } case OPT_e: /* Edit */ tmp_fname = xasprintf("%s.%u", crontab_dir, (unsigned)getpid()); /* No O_EXCL: we don't want to be stuck if earlier crontabs * were killed, leaving stale temp file behind */ src_fd = xopen3(tmp_fname, O_RDWR|O_CREAT|O_TRUNC, 0600); fchown(src_fd, pas->pw_uid, pas->pw_gid); fd = open(pas->pw_name, O_RDONLY); if (fd >= 0) { bb_copyfd_eof(fd, src_fd); close(fd); xlseek(src_fd, 0, SEEK_SET); } close_on_exec_on(src_fd); /* don't want editor to see this fd */ edit_file(pas, tmp_fname); /* fall through */ case 0: /* Replace (no -l, -e, or -r were given) */ new_fname = xasprintf("%s.new", pas->pw_name); fd = open(new_fname, O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600); if (fd >= 0) { bb_copyfd_eof(src_fd, fd); close(fd); xrename(new_fname, pas->pw_name); } else { bb_error_msg("cannot create %s/%s", crontab_dir, new_fname); } if (tmp_fname) unlink(tmp_fname); /*free(tmp_fname);*/ /*free(new_fname);*/ } /* switch */ /* Bump notification file. Handle window where crond picks file up * before we can write our entry out. */ while ((fd = open(CRONUPDATE, O_WRONLY|O_CREAT|O_APPEND, 0600)) >= 0) { struct stat st; fdprintf(fd, "%s\n", pas->pw_name); if (fstat(fd, &st) != 0 || st.st_nlink != 0) { /*close(fd);*/ break; } /* st.st_nlink == 0: * file was deleted, maybe crond missed our notification */ close(fd); /* loop */ } if (fd < 0) { bb_error_msg("cannot append to %s/%s", crontab_dir, CRONUPDATE); } return 0; }
int makedevs_main(int argc UNUSED_PARAM, char **argv) { parser_t *parser; char *line = (char *)"-"; int ret = EXIT_SUCCESS; opt_complementary = "=1"; /* exactly one param */ getopt32(argv, "d:", &line); argv += optind; xchdir(*argv); /* ensure root dir exists */ umask(0); printf("rootdir=%s\ntable=", *argv); if (NOT_LONE_DASH(line)) { printf("'%s'\n", line); } else { puts("<stdin>"); } parser = config_open(line); while (config_read(parser, &line, 1, 1, "# \t", PARSE_NORMAL)) { int linenum; char type; unsigned mode = 0755; unsigned major = 0; unsigned minor = 0; unsigned count = 0; unsigned increment = 0; unsigned start = 0; char name[41]; char user[41]; char group[41]; char *full_name = name; uid_t uid; gid_t gid; linenum = parser->lineno; if ((2 > sscanf(line, "%40s %c %o %40s %40s %u %u %u %u %u", name, &type, &mode, user, group, &major, &minor, &start, &increment, &count)) || ((unsigned)(major | minor | start | count | increment) > 255) ) { bb_error_msg("invalid line %d: '%s'", linenum, line); ret = EXIT_FAILURE; continue; } gid = (*group) ? get_ug_id(group, xgroup2gid) : getgid(); uid = (*user) ? get_ug_id(user, xuname2uid) : getuid(); /* We are already in the right root dir, * so make absolute paths relative */ if ('/' == *full_name) full_name++; if (type == 'd') { bb_make_directory(full_name, mode | S_IFDIR, FILEUTILS_RECUR); if (chown(full_name, uid, gid) == -1) { chown_fail: bb_perror_msg("line %d: can't chown %s", linenum, full_name); ret = EXIT_FAILURE; continue; } if (chmod(full_name, mode) < 0) { chmod_fail: bb_perror_msg("line %d: can't chmod %s", linenum, full_name); ret = EXIT_FAILURE; continue; } } else if (type == 'f') { struct stat st; if ((stat(full_name, &st) < 0 || !S_ISREG(st.st_mode))) { bb_perror_msg("line %d: regular file '%s' does not exist", linenum, full_name); ret = EXIT_FAILURE; continue; } if (chown(full_name, uid, gid) < 0) goto chown_fail; if (chmod(full_name, mode) < 0) goto chmod_fail; } else { dev_t rdev; unsigned i; char *full_name_inc; if (type == 'p') { mode |= S_IFIFO; } else if (type == 'c') { mode |= S_IFCHR; } else if (type == 'b') { mode |= S_IFBLK; } else { bb_error_msg("line %d: unsupported file type %c", linenum, type); ret = EXIT_FAILURE; continue; } full_name_inc = xmalloc(strlen(full_name) + sizeof(int)*3 + 2); if (count) count--; for (i = start; i <= start + count; i++) { sprintf(full_name_inc, count ? "%s%u" : "%s", full_name, i); rdev = makedev(major, minor + (i - start) * increment); if (mknod(full_name_inc, mode, rdev) != 0 && errno != EEXIST ) { bb_perror_msg("line %d: can't create node %s", linenum, full_name_inc); ret = EXIT_FAILURE; } else if (chown(full_name_inc, uid, gid) < 0) { bb_perror_msg("line %d: can't chown %s", linenum, full_name_inc); ret = EXIT_FAILURE; } else if (chmod(full_name_inc, mode) < 0) { bb_perror_msg("line %d: can't chmod %s", linenum, full_name_inc); ret = EXIT_FAILURE; } } free(full_name_inc); } } if (ENABLE_FEATURE_CLEAN_UP) config_close(parser); return ret; }
int sort_main(int argc, char **argv) { FILE *fp, *outfile = stdout; char *line, **lines = NULL; char *str_ignored, *str_o, *str_t; llist_t *lst_k = NULL; int i, flag; int linecount = 0; xfunc_error_retval = 2; /* Parse command line options */ /* -o and -t can be given at most once */ opt_complementary = "o--o:t--t:" /* -t, -o: maximum one of each */ "k::"; /* -k takes list */ getopt32(argv, OPT_STR, &str_ignored, &str_ignored, &str_o, &lst_k, &str_t); #if ENABLE_FEATURE_SORT_BIG if (option_mask32 & FLAG_o) outfile = xfopen(str_o, "w"); if (option_mask32 & FLAG_t) { if (!str_t[0] || str_t[1]) bb_error_msg_and_die("bad -t parameter"); key_separator = str_t[0]; } /* parse sort key */ while (lst_k) { enum { FLAG_allowed_for_k = FLAG_n | /* Numeric sort */ FLAG_g | /* Sort using strtod() */ FLAG_M | /* Sort date */ FLAG_b | /* Ignore leading blanks */ FLAG_r | /* Reverse */ FLAG_d | /* Ignore !(isalnum()|isspace()) */ FLAG_f | /* Force uppercase */ FLAG_i | /* Ignore !isprint() */ 0 }; struct sort_key *key = add_key(); char *str_k = lst_k->data; const char *temp2; i = 0; /* i==0 before comma, 1 after (-k3,6) */ while (*str_k) { /* Start of range */ /* Cannot use bb_strtou - suffix can be a letter */ key->range[2*i] = str2u(&str_k); if (*str_k == '.') { str_k++; key->range[2*i+1] = str2u(&str_k); } while (*str_k) { if (*str_k == ',' && !i++) { str_k++; break; } /* no else needed: fall through to syntax error because comma isn't in OPT_STR */ temp2 = strchr(OPT_STR, *str_k); if (!temp2) bb_error_msg_and_die("unknown key option"); flag = 1 << (temp2 - OPT_STR); if (flag & ~FLAG_allowed_for_k) bb_error_msg_and_die("unknown sort type"); /* b after ',' means strip _trailing_ space */ if (i && flag == FLAG_b) flag = FLAG_bb; key->flags |= flag; str_k++; } } /* leaking lst_k... */ lst_k = lst_k->link; } #endif /* global b strips leading and trailing spaces */ if (option_mask32 & FLAG_b) option_mask32 |= FLAG_bb; /* Open input files and read data */ for (i = argv[optind] ? optind : optind-1; argv[i]; i++) { fp = stdin; if (i >= optind && NOT_LONE_DASH(argv[i])) fp = xfopen(argv[i], "r"); for (;;) { line = GET_LINE(fp); if (!line) break; if (!(linecount & 63)) lines = xrealloc(lines, sizeof(char *) * (linecount + 64)); lines[linecount++] = line; } fclose(fp); } #if ENABLE_FEATURE_SORT_BIG /* if no key, perform alphabetic sort */ if (!key_list) add_key()->range[0] = 1; /* handle -c */ if (option_mask32 & FLAG_c) { int j = (option_mask32 & FLAG_u) ? -1 : 0; for (i = 1; i < linecount; i++) if (compare_keys(&lines[i-1], &lines[i]) > j) { fprintf(stderr, "Check line %d\n", i); return 1; } return 0; } #endif /* Perform the actual sort */ qsort(lines, linecount, sizeof(char *), compare_keys); /* handle -u */ if (option_mask32 & FLAG_u) { flag = 0; /* coreutils 6.3 drop lines for which only key is the same */ /* -- disabling last-resort compare... */ option_mask32 |= FLAG_s; for (i = 1; i < linecount; i++) { if (!compare_keys(&lines[flag], &lines[i])) free(lines[i]); else lines[++flag] = lines[i]; } if (linecount) linecount = flag+1; } /* Print it */ for (i = 0; i < linecount; i++) fprintf(outfile, "%s\n", lines[i]); fflush_stdout_and_exit(EXIT_SUCCESS); }
int md5_sha1_sum_main(int argc, char **argv) { int return_value = EXIT_SUCCESS; uint8_t *hash_value; unsigned flags; hash_algo_t hash_algo = ENABLE_MD5SUM ? (ENABLE_SHA1SUM ? (**argv=='m' ? HASH_MD5 : HASH_SHA1) : HASH_MD5) : HASH_SHA1; if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK) flags = getopt32(argc, argv, "scw"); else optind = 1; if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && !(flags & FLAG_CHECK)) { if (flags & FLAG_SILENT) { bb_error_msg_and_die ("-%c is meaningful only when verifying checksums", 's'); } else if (flags & FLAG_WARN) { bb_error_msg_and_die ("-%c is meaningful only when verifying checksums", 'w'); } } if (argc == optind) { argv[argc++] = "-"; } if (ENABLE_FEATURE_MD5_SHA1_SUM_CHECK && (flags & FLAG_CHECK)) { FILE *pre_computed_stream; int count_total = 0; int count_failed = 0; char *file_ptr = argv[optind]; char *line; if (optind + 1 != argc) { bb_error_msg_and_die ("only one argument may be specified when using -c"); } pre_computed_stream = stdin; if (NOT_LONE_DASH(file_ptr)) { pre_computed_stream = xfopen(file_ptr, "r"); } while ((line = xmalloc_getline(pre_computed_stream)) != NULL) { char *filename_ptr; count_total++; filename_ptr = strstr(line, " "); /* handle format for binary checksums */ if (filename_ptr == NULL) { filename_ptr = strstr(line, " *"); } if (filename_ptr == NULL) { if (flags & FLAG_WARN) { bb_error_msg("invalid format"); } count_failed++; return_value = EXIT_FAILURE; free(line); continue; } *filename_ptr = '\0'; filename_ptr += 2; hash_value = hash_file(filename_ptr, hash_algo); if (hash_value && (strcmp((char*)hash_value, line) == 0)) { if (!(flags & FLAG_SILENT)) printf("%s: OK\n", filename_ptr); } else { if (!(flags & FLAG_SILENT)) printf("%s: FAILED\n", filename_ptr); count_failed++; return_value = EXIT_FAILURE; } /* possible free(NULL) */ free(hash_value); free(line); } if (count_failed && !(flags & FLAG_SILENT)) { bb_error_msg("WARNING: %d of %d computed checksums did NOT match", count_failed, count_total); } /* if (fclose_if_not_stdin(pre_computed_stream) == EOF) { bb_perror_msg_and_die("cannot close file %s", file_ptr); } */ } else { while (optind < argc) { char *file_ptr = argv[optind++]; hash_value = hash_file(file_ptr, hash_algo); if (hash_value == NULL) { return_value = EXIT_FAILURE; } else { printf("%s %s\n", hash_value, file_ptr); free(hash_value); } } } return return_value; }
int tail_main(int argc, char **argv) { unsigned count = 10; unsigned sleep_period = 1; bool from_top; int header_threshhold = 1; const char *str_c, *str_n, *str_s; char *tailbuf; size_t tailbufsize; int taillen = 0; int newline = 0; int nfiles, nread, nwrite, seen, i, opt; int *fds; char *s, *buf; const char *fmt; #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_TAIL /* Allow legacy syntax of an initial numeric option without -n. */ if (argc >= 2 && (argv[1][0] == '+' || argv[1][0] == '-') && isdigit(argv[1][1]) ) { argv[0] = (char*)"-n"; argv--; argc++; } #endif opt = getopt32(argc, argv, "fc:n:" USE_FEATURE_FANCY_TAIL("qs:v"), &str_c, &str_n, &str_s); #define FOLLOW (opt & 0x1) #define COUNT_BYTES (opt & 0x2) //if (opt & 0x1) // -f if (opt & 0x2) count = eat_num(str_c); // -c if (opt & 0x4) count = eat_num(str_n); // -n #if ENABLE_FEATURE_FANCY_TAIL if (opt & 0x8) header_threshhold = INT_MAX; // -q if (opt & 0x10) sleep_period = xatou(str_s); // -s if (opt & 0x20) header_threshhold = 0; // -v #endif argc -= optind; argv += optind; from_top = status; /* open all the files */ fds = xmalloc(sizeof(int) * (argc + 1)); status = nfiles = i = 0; if (argc == 0) { struct stat statbuf; if (!fstat(STDIN_FILENO, &statbuf) && S_ISFIFO(statbuf.st_mode)) { opt &= ~1; /* clear FOLLOW */ } *argv = (char *) bb_msg_standard_input; goto DO_STDIN; } do { if (NOT_LONE_DASH(argv[i])) { fds[nfiles] = open(argv[i], O_RDONLY); if (fds[nfiles] < 0) { bb_perror_msg("%s", argv[i]); status = EXIT_FAILURE; continue; } } else { DO_STDIN: /* "-" */ fds[nfiles] = STDIN_FILENO; } argv[nfiles] = argv[i]; ++nfiles; } while (++i < argc); if (!nfiles) bb_error_msg_and_die("no files"); tailbufsize = BUFSIZ; /* tail the files */ if (!from_top && COUNT_BYTES) { if (tailbufsize < count) { tailbufsize = count + BUFSIZ; } } buf = tailbuf = xmalloc(tailbufsize); fmt = header_fmt + 1; /* Skip header leading newline on first output. */ i = 0; do { /* Be careful. It would be possible to optimize the count-bytes * case if the file is seekable. If you do though, remember that * starting file position may not be the beginning of the file. * Beware of backing up too far. See example in wc.c. */ if (!(count | from_top) && lseek(fds[i], 0, SEEK_END) >= 0) { continue; } if (nfiles > header_threshhold) { tail_xprint_header(fmt, argv[i]); fmt = header_fmt; } buf = tailbuf; taillen = 0; seen = 1; newline = 0; while ((nread = tail_read(fds[i], buf, tailbufsize-taillen)) > 0) { if (from_top) { nwrite = nread; if (seen < count) { if (COUNT_BYTES) { nwrite -= (count - seen); seen = count; } else { s = buf; do { --nwrite; if (*s++ == '\n' && ++seen == count) { break; } } while (nwrite); } } xwrite(STDOUT_FILENO, buf + nread - nwrite, nwrite); } else if (count) { if (COUNT_BYTES) { taillen += nread; if (taillen > count) { memmove(tailbuf, tailbuf + taillen - count, count); taillen = count; } } else { int k = nread; int nbuf = 0; while (k) { --k; if (buf[k] == '\n') { ++nbuf; } } if (newline + nbuf < count) { newline += nbuf; taillen += nread; } else { int extra = 0; if (buf[nread-1] != '\n') { extra = 1; } k = newline + nbuf + extra - count; s = tailbuf; while (k) { if (*s == '\n') { --k; } ++s; } taillen += nread - (s - tailbuf); memmove(tailbuf, s, taillen); newline = count - extra; } if (tailbufsize < taillen + BUFSIZ) { tailbufsize = taillen + BUFSIZ; tailbuf = xrealloc(tailbuf, tailbufsize); } } buf = tailbuf + taillen; } } if (!from_top) { xwrite(STDOUT_FILENO, tailbuf, taillen); } taillen = 0; } while (++i < nfiles); buf = xrealloc(tailbuf, BUFSIZ); fmt = NULL; if (FOLLOW) while (1) { sleep(sleep_period); i = 0; do { if (nfiles > header_threshhold) { fmt = header_fmt; } while ((nread = tail_read(fds[i], buf, sizeof(buf))) > 0) { if (fmt) { tail_xprint_header(fmt, argv[i]); fmt = NULL; } xwrite(STDOUT_FILENO, buf, nread); } } while (++i < nfiles); } return status; }
int ftp_msend2(ftp_host_info_t *server, FILE *control_stream, file_path_t *file_path, int file_cnt) { struct stat sbuf; char buf[512]; int fd_data; int* fd_local = NULL; int response; int i = 0; if(file_cnt == 0) return -1; fd_local = (int*)malloc(sizeof(int)*file_cnt); if(fd_local == NULL){ lib_error("[%s] malloc err!!", __FUNCTION__); return -1; } for(i=0;i<file_cnt;i++){ memset(buf, 0, sizeof(buf)); /* Connect to the data socket */ if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { ftp_die("PASV", buf); } fd_data = connect_ftpdata(server, buf); if(fd_data < 0){ lib_error("[%s] connect_ftpdata err!!", __FUNCTION__); return -1; } /* get the local file */ fd_local[i] = STDIN_FILENO; if (NOT_LONE_DASH(file_path[i].local_path)) { //printf("%d: lc_path : %s, rt_path:%s\n",i, file_path[i].local_path, file_path[i].server_path); fd_local[i] = open(file_path[i].local_path, O_RDONLY, 0666); if(fd_local[i] < 0){ lib_error("[%s] open err!!", __FUNCTION__); close(fd_data); return -1; } fstat(fd_local[i], &sbuf); sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size); response = ftpcmd(buf, NULL, control_stream, buf); switch (response) { case 200: case 202: break; default: ftp_die("ALLO", buf); break; } } response = ftpcmd("STOR", file_path[i].server_path, control_stream, buf); switch (response) { case 125: case 150: break; default: ftp_die("STOR", buf); close(fd_local[i]); close(fd_data); goto ftp_msend_quit_error; } /* transfer the file */ if (copyfd_eof(fd_local[i], fd_data, 0) == -1) { close(fd_data); close(fd_local[i]); goto ftp_msend_quit_error; } /* close it all down */ close(fd_local[i]); close(fd_data); if (ftpcmd(NULL, NULL, control_stream, buf) != 226) { ftp_die("close", buf); } } ftpcmd("QUIT", NULL, control_stream, buf); return 0; ftp_msend_quit_error: ftpcmd("QUIT", NULL, control_stream, buf); return -1; }
int ftp_send(ftp_host_info_t *server, FILE *control_stream, const char *server_path, char *local_path) { struct stat sbuf; char buf[512]; int fd_data; int fd_local; int response; /* Connect to the data socket */ if (ftpcmd("PASV", NULL, control_stream, buf) != 227) { ftp_die("PASV", buf); } fd_data = connect_ftpdata(server, buf); if(fd_data < 0){ lib_error("[%s] connect_ftpdata err!!", __FUNCTION__); return -1; } /* get the local file */ fd_local = STDIN_FILENO; if (NOT_LONE_DASH(local_path)) { fd_local = open(local_path, O_RDONLY, 0666); if(fd_local < 0){ lib_error("[%s] open err!!", __FUNCTION__); close(fd_data); return -1; } fstat(fd_local, &sbuf); sprintf(buf, "ALLO %"OFF_FMT"u", sbuf.st_size); response = ftpcmd(buf, NULL, control_stream, buf); switch (response) { case 200: case 202: break; default: ftp_die("ALLO", buf); break; } } response = ftpcmd("STOR", server_path, control_stream, buf); switch (response) { case 125: case 150: break; default: ftp_die("STOR", buf); close(fd_local); close(fd_data); return -1; } /* transfer the file */ if (copyfd_eof(fd_local, fd_data, 0) == -1) { close(fd_data); close(fd_local); return -1; } /* close it all down */ close(fd_local); close(fd_data); if (ftpcmd(NULL, NULL, control_stream, buf) != 226) { ftp_die("close", buf); } //ftpcmd("NOOP", NULL, control_stream, buf); ftpcmd("QUIT", NULL, control_stream, buf); return 0; }