int ftp_putfile(SESSION handle, const char *lname, const char *rname, uint8_t how, uint8_t xfrmode) { FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle; FAR char *abslpath; struct stat statbuf; FILE *finstream; int ret; /* Don't call this with a NULL local file name */ DEBUGASSERT(lname); /* If the remote name is not specified, then it is assumed to the same as * the local file name. */ if (!rname) { rname = lname; } /* Get the full path to the local file */ abslpath = ftpc_abslpath(session, lname); if (!abslpath) { ndbg("ftpc_abslpath(%s) failed: %d\n", errno); goto errout; } /* Make sure that the local file exists */ ret = stat(abslpath, &statbuf); if (ret != OK) { ndbg("stat(%s) failed: %d\n", errno); goto errout_with_abspath; } /* Make sure that the local name does not refer to a directory */ if (S_ISDIR(statbuf.st_mode)) { ndbg("%s is a directory\n", abslpath); goto errout_with_abspath; } /* Open the local file for reading */ finstream = fopen(abslpath, "r"); if (!finstream) { ndbg("fopen() failed: %d\n", errno); goto errout_with_abspath; } /* Are we resuming a transfer? */ session->offset = 0; if (how == FTPC_PUT_RESUME) { /* Yes... Get the size of the file. This will only work if the * server supports the SIZE command. */ session->offset = ftpc_filesize(session, rname); if (session->offset == (off_t)ERROR) { ndbg("Failed to get size of remote file: %s\n", rname); goto errout_with_instream; } else { /* Seek to the offset in the file corresponding to the size * that we have already sent. */ ret = fseek(finstream, session->offset, SEEK_SET); if (ret != OK) { ndbg("fseek failed: %d\n", errno); goto errout_with_instream; } } } /* Send the file */ ret = ftpc_sendfile(session, rname, finstream, how, xfrmode); if (ret == OK) { fclose(finstream); free(abslpath); return OK; } /* Various error exits */ errout_with_instream: fclose(finstream); errout_with_abspath: free(abslpath); errout: return ERROR; }
int ftpc_getfile(SESSION handle, FAR const char *rname, FAR const char *lname, uint8_t how, uint8_t xfrmode) { FAR struct ftpc_session_s *session = (FAR struct ftpc_session_s *)handle; struct stat statbuf; FILE *loutstream; FAR char *abslpath; off_t offset; int ret; /* Don't call this with a NULL remote file name */ DEBUGASSERT(rname); /* If the local name is not specified, then it is assumed to the same as * the remote file name. */ if (!lname) { lname = rname; } /* Get the full path to the local file */ abslpath = ftpc_abslpath(session, lname); if (!abslpath) { ndbg("ftpc_abslpath(%s) failed: %d\n", errno); goto errout; } /* Get information about the local file */ ret = stat(abslpath, &statbuf); if (ret == 0) { /* It already exists. Is it a directory? */ if (S_ISDIR(statbuf.st_mode)) { ndbg("'%s' is a directory\n", abslpath); goto errout_with_abspath; } } /* Is it write-able? */ #ifdef S_IWRITE if (!(statbuf.st_mode & S_IWRITE)) { ndbg("'%s' permission denied\n", abslpath); goto errout_with_abspath; } #endif /* Are we resuming the transfers? Is so then the starting offset is the * size of the existing, partial file. */ if (how == FTPC_GET_RESUME) { offset = statbuf.st_size; } else { offset = 0; } /* Setup to receive the file */ ret = ftpc_recvinit(session, rname, xfrmode, offset); if (ret != OK) { ndbg("ftpc_recvinit failed\n"); goto errout_with_abspath; } loutstream = fopen(abslpath, (offset > 0 || (how == FTPC_GET_APPEND)) ? "a" : "w"); if (!loutstream) { ndbg("fopen failed: %d\n", errno); goto errout_with_abspath; } /* If the offset is non-zero, then seek to that offset in the file */ if (offset > 0) { ret = fseek(loutstream, offset, SEEK_SET); if (ret != OK) { ndbg("fseek failed: %d\n", errno); goto errout_with_outstream; } } /* And receive the new file data */ if (xfrmode == FTPC_XFRMODE_ASCII) { ret = ftpc_recvtext(session, session->data.instream, loutstream); } else { ret = ftpc_recvbinary(session, session->data.instream, loutstream); } ftpc_sockclose(&session->data); if (ret == 0) { fptc_getreply(session); } /* Check for success */ if (ret == OK && !FTPC_INTERRUPTED(session)) { fclose(loutstream); free(abslpath); return OK; } /* Various error exits */ errout_with_outstream: fclose(loutstream); errout_with_abspath: free(abslpath); session->offset = 0; errout: return ERROR; }