- Timestamp:
- Jan 13, 2020 10:26:27 AM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 135661
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/ftp.h
r82715 r82723 31 31 #endif 32 32 33 #include <iprt/fs.h> 33 34 #include <iprt/types.h> 34 35 … … 130 131 /** Not logged in. */ 131 132 RTFTPSERVER_REPLY_NOT_LOGGED_IN = 530, 133 /** Requested action not taken. */ 134 RTFTPSERVER_REPLY_REQ_ACTION_NOT_TAKEN = 550, 132 135 /** The usual 32-bit hack. */ 133 136 RTFTPSERVER_REPLY_32BIT_HACK = 0x7fffffff … … 179 182 * 180 183 * @returns VBox status code. 184 * @param pData Pointer to generic callback data. 181 185 * @param pcszUser User name. 182 186 */ … … 186 190 * 187 191 * @returns VBox status code. 192 * @param pData Pointer to generic callback data. 188 193 * @param pcszUser User name to authenticate. 189 194 * @param pcszPassword Password to authenticate with. … … 194 199 * 195 200 * @returns VBox status code. 196 * @param p cszUser User name which disconnected.201 * @param pData Pointer to generic callback data. 197 202 */ 198 203 DECLCALLBACKMEMBER(int, pfnOnUserDisconnect)(PRTFTPCALLBACKDATA pData); 199 204 /** 205 * Callback which gets invoked when the client wants to retrieve the size of a specific file. 206 * 207 * @returns VBox status code. 208 * @param pData Pointer to generic callback data. 209 * @param pcszPath Path of file to retrieve size for. 210 * @param puSize Where to store the file size on success. 211 */ 212 DECLCALLBACKMEMBER(int, pfnOnFileGetSize)(PRTFTPCALLBACKDATA pData, const char *pcszPath, uint64_t *puSize); 213 /** 214 * Callback which gets invoked when the client wants to retrieve information about a file. 215 * 216 * @param pData Pointer to generic callback data. 217 * @param pcszPath Path of file / directory to "stat". Optional. If NULL, the current directory will be used. 218 * @param pFsObjInfo Where to return the RTFSOBJINFO data on success. 219 * @returns VBox status code. 220 */ 221 DECLCALLBACKMEMBER(int, pfnOnFileStat)(PRTFTPCALLBACKDATA pData, const char *pcszPath, PRTFSOBJINFO pFsObjInfo); 222 /** 200 223 * Callback which gets invoked when setting the current working directory. 201 224 * 202 225 * @returns VBox status code. 226 * @param pData Pointer to generic callback data. 203 227 * @param pcszCWD Current working directory to set. 204 228 */ … … 208 232 * 209 233 * @returns VBox status code. 234 * @param pData Pointer to generic callback data. 210 235 * @param pszPWD Where to store the current working directory. 211 236 * @param cbPWD Size of buffer in bytes. … … 216 241 * 217 242 * @returns VBox status code. 243 * @param pData Pointer to generic callback data. 218 244 */ 219 245 DECLCALLBACKMEMBER(int, pfnOnPathUp)(PRTFTPCALLBACKDATA pData); … … 221 247 * Callback which gets invoked when the client wants to list a directory or file. 222 248 * 249 * @param pData Pointer to generic callback data. 223 250 * @param pcszPath Path of file / directory to list. Optional. If NULL, the current directory will be listed. 224 251 * @param ppvData Where to return the listing data. Must be free'd by the caller. -
trunk/src/VBox/Runtime/generic/ftp-server.cpp
r82716 r82723 2 2 /** @file 3 3 * Generic FTP server (RFC 959) implementation. 4 * Partly also implements RFC 3659 (Extensions to FTP, for "SIZE", ++). 4 5 */ 5 6 … … 129 130 /** Recursively gets a directory (and its contents). */ 130 131 RTFTPSERVER_CMD_RGET, 132 /** Retrieves the size of a file. */ 133 RTFTPSERVER_CMD_SIZE, 131 134 /** Retrieves the current status of a transfer. */ 132 135 RTFTPSERVER_CMD_STAT, … … 234 237 static FNRTFTPSERVERCMD rtFtpServerHandleRETR; 235 238 static FNRTFTPSERVERCMD rtFtpServerHandleRGET; 239 static FNRTFTPSERVERCMD rtFtpServerHandleSIZE; 236 240 static FNRTFTPSERVERCMD rtFtpServerHandleSTAT; 237 241 static FNRTFTPSERVERCMD rtFtpServerHandleSYST; … … 269 273 { RTFTPSERVER_CMD_RETR, "RETR", rtFtpServerHandleRETR }, 270 274 { RTFTPSERVER_CMD_RGET, "RGET", rtFtpServerHandleRGET }, 275 { RTFTPSERVER_CMD_SIZE, "SIZE", rtFtpServerHandleSIZE }, 271 276 { RTFTPSERVER_CMD_STAT, "STAT", rtFtpServerHandleSTAT }, 272 277 { RTFTPSERVER_CMD_SYST, "SYST", rtFtpServerHandleSYST }, … … 301 306 * @returns VBox status code. 302 307 * @param pClient Client to reply to. 303 * @param pcszStr String to reply. 304 */ 305 static int rtFtpServerSendReplyStr(PRTFTPSERVERCLIENT pClient, const char *pcszStr) 306 { 307 char *pszReply; 308 int rc = RTStrAPrintf(&pszReply, "%s\r\n", pcszStr); 309 if (RT_SUCCESS(rc)) 310 { 311 rc = RTTcpWrite(pClient->hSocket, pszReply, strlen(pszReply) + 1); 312 RTStrFree(pszReply); 313 return rc; 314 } 315 316 return VERR_NO_MEMORY; 308 * @param pcszFormat Format to reply. 309 * @param ... Format arguments. 310 */ 311 static int rtFtpServerSendReplyStr(PRTFTPSERVERCLIENT pClient, const char *pcszFormat, ...) 312 { 313 va_list args; 314 va_start(args, pcszFormat); 315 char *psz = NULL; 316 const int cch = RTStrAPrintfV(&psz, pcszFormat, args); 317 va_end(args); 318 AssertReturn(cch > 0, VERR_NO_MEMORY); 319 320 int rc = RTStrAAppend(&psz, "\r\n"); 321 AssertRCReturn(rc, rc); 322 323 rc = RTTcpWrite(pClient->hSocket, psz, strlen(psz) + 1 /* Include termination */); 324 325 RTStrFree(psz); 326 327 return rc; 317 328 } 318 329 … … 342 353 } 343 354 355 /** 356 * Converts a RTFSOBJINFO struct to a string. 357 * 358 * @returns VBox status code. 359 * @param pObjInfo RTFSOBJINFO object to convert. 360 * @param pszFsObjInfo Where to store the output string. 361 * @param cbFsObjInfo Size of the output string in bytes. 362 */ 363 static int rtFtpServerFsObjInfoToStr(PRTFSOBJINFO pObjInfo, char *pszFsObjInfo, size_t cbFsObjInfo) 364 { 365 RTFMODE fMode = pObjInfo->Attr.fMode; 366 char chFileType; 367 switch (fMode & RTFS_TYPE_MASK) 368 { 369 case RTFS_TYPE_FIFO: chFileType = 'f'; break; 370 case RTFS_TYPE_DEV_CHAR: chFileType = 'c'; break; 371 case RTFS_TYPE_DIRECTORY: chFileType = 'd'; break; 372 case RTFS_TYPE_DEV_BLOCK: chFileType = 'b'; break; 373 case RTFS_TYPE_FILE: chFileType = '-'; break; 374 case RTFS_TYPE_SYMLINK: chFileType = 'l'; break; 375 case RTFS_TYPE_SOCKET: chFileType = 's'; break; 376 case RTFS_TYPE_WHITEOUT: chFileType = 'w'; break; 377 default: chFileType = '?'; break; 378 } 379 380 char szTimeBirth[RTTIME_STR_LEN]; 381 char szTimeChange[RTTIME_STR_LEN]; 382 char szTimeModification[RTTIME_STR_LEN]; 383 char szTimeAccess[RTTIME_STR_LEN]; 384 385 #define INFO_TO_STR(a_Format, ...) \ 386 do \ 387 { \ 388 const ssize_t cchSize = RTStrPrintf2(szTemp, sizeof(szTemp), a_Format, __VA_ARGS__); \ 389 AssertReturn(cchSize > 0, VERR_BUFFER_OVERFLOW); \ 390 const int rc2 = RTStrCat(pszFsObjInfo, cbFsObjInfo, szTemp); \ 391 AssertRCReturn(rc2, rc2); \ 392 } while (0); 393 394 char szTemp[32]; 395 396 INFO_TO_STR("%c", chFileType); 397 INFO_TO_STR("%c%c%c", 398 fMode & RTFS_UNIX_IRUSR ? 'r' : '-', 399 fMode & RTFS_UNIX_IWUSR ? 'w' : '-', 400 fMode & RTFS_UNIX_IXUSR ? 'x' : '-'); 401 INFO_TO_STR("%c%c%c", 402 fMode & RTFS_UNIX_IRGRP ? 'r' : '-', 403 fMode & RTFS_UNIX_IWGRP ? 'w' : '-', 404 fMode & RTFS_UNIX_IXGRP ? 'x' : '-'); 405 INFO_TO_STR("%c%c%c", 406 fMode & RTFS_UNIX_IROTH ? 'r' : '-', 407 fMode & RTFS_UNIX_IWOTH ? 'w' : '-', 408 fMode & RTFS_UNIX_IXOTH ? 'x' : '-'); 409 410 INFO_TO_STR( " %c%c%c%c%c%c%c%c%c%c%c%c%c%c", 411 fMode & RTFS_DOS_READONLY ? 'R' : '-', 412 fMode & RTFS_DOS_HIDDEN ? 'H' : '-', 413 fMode & RTFS_DOS_SYSTEM ? 'S' : '-', 414 fMode & RTFS_DOS_DIRECTORY ? 'D' : '-', 415 fMode & RTFS_DOS_ARCHIVED ? 'A' : '-', 416 fMode & RTFS_DOS_NT_DEVICE ? 'd' : '-', 417 fMode & RTFS_DOS_NT_NORMAL ? 'N' : '-', 418 fMode & RTFS_DOS_NT_TEMPORARY ? 'T' : '-', 419 fMode & RTFS_DOS_NT_SPARSE_FILE ? 'P' : '-', 420 fMode & RTFS_DOS_NT_REPARSE_POINT ? 'J' : '-', 421 fMode & RTFS_DOS_NT_COMPRESSED ? 'C' : '-', 422 fMode & RTFS_DOS_NT_OFFLINE ? 'O' : '-', 423 fMode & RTFS_DOS_NT_NOT_CONTENT_INDEXED ? 'I' : '-', 424 fMode & RTFS_DOS_NT_ENCRYPTED ? 'E' : '-'); 425 426 INFO_TO_STR( " %d %4d %4d %10lld %10lld", 427 pObjInfo->Attr.u.Unix.cHardlinks, 428 pObjInfo->Attr.u.Unix.uid, 429 pObjInfo->Attr.u.Unix.gid, 430 pObjInfo->cbObject, 431 pObjInfo->cbAllocated); 432 433 INFO_TO_STR( " %s %s %s %s", 434 RTTimeSpecToString(&pObjInfo->BirthTime, szTimeBirth, sizeof(szTimeBirth)), 435 RTTimeSpecToString(&pObjInfo->ChangeTime, szTimeChange, sizeof(szTimeChange)), 436 RTTimeSpecToString(&pObjInfo->ModificationTime, szTimeModification, sizeof(szTimeModification)), 437 RTTimeSpecToString(&pObjInfo->AccessTime, szTimeAccess, sizeof(szTimeAccess)) ); 438 439 #undef INFO_TO_STR 440 441 return VINF_SUCCESS; 442 } 443 344 444 345 445 /********************************************************************************************************************************* … … 497 597 } 498 598 599 static int rtFtpServerHandleSIZE(PRTFTPSERVERCLIENT pClient, uint8_t cArgs, const char * const *apcszArgs) 600 { 601 if (cArgs != 1) 602 return VERR_INVALID_PARAMETER; 603 604 int rc; 605 606 const char *pcszPath = apcszArgs[0]; 607 uint64_t uSize = 0; 608 609 RTFTPSERVER_HANDLE_CALLBACK_VA(pfnOnFileGetSize, pcszPath, &uSize); 610 611 if (RT_SUCCESS(rc)) 612 { 613 rc = rtFtpServerSendReplyStr(pClient, "213 %RU64\r\n", uSize); 614 } 615 else 616 { 617 int rc2 = rtFtpServerSendReplyRc(pClient, RTFTPSERVER_REPLY_REQ_ACTION_NOT_TAKEN); 618 AssertRC(rc2); 619 } 620 621 return rc; 622 } 623 499 624 static int rtFtpServerHandleSTAT(PRTFTPSERVERCLIENT pClient, uint8_t cArgs, const char * const *apcszArgs) 500 625 { 501 RT_NOREF(pClient, cArgs, apcszArgs); 502 503 /** @todo Anything to do here? */ 504 return VERR_NOT_IMPLEMENTED; 626 if (cArgs != 1) 627 return VERR_INVALID_PARAMETER; 628 629 int rc; 630 631 RTFSOBJINFO objInfo; 632 RT_ZERO(objInfo); 633 634 const char *pcszPath = apcszArgs[0]; 635 636 RTFTPSERVER_HANDLE_CALLBACK_VA(pfnOnFileStat, pcszPath, &objInfo); 637 638 if (RT_SUCCESS(rc)) 639 { 640 char szFsObjInfo[_4K]; /** @todo Check this size. */ 641 rc = rtFtpServerFsObjInfoToStr(&objInfo, szFsObjInfo, sizeof(szFsObjInfo)); 642 if (RT_SUCCESS(rc)) 643 { 644 char szFsPathInfo[RTPATH_MAX + 16]; 645 const ssize_t cchPathInfo = RTStrPrintf2(szFsPathInfo, sizeof(szFsPathInfo), " %2zu %s\n", strlen(pcszPath), pcszPath); 646 if (cchPathInfo > 0) 647 { 648 rc = RTStrCat(szFsObjInfo, sizeof(szFsObjInfo), szFsPathInfo); 649 if (RT_SUCCESS(rc)) 650 rc = rtFtpServerSendReplyStr(pClient, szFsObjInfo); 651 } 652 else 653 rc = VERR_BUFFER_OVERFLOW; 654 } 655 } 656 657 if (RT_FAILURE(rc)) 658 { 659 int rc2 = rtFtpServerSendReplyRc(pClient, RTFTPSERVER_REPLY_REQ_ACTION_NOT_TAKEN); 660 AssertRC(rc2); 661 } 662 663 return rc; 505 664 } 506 665 -
trunk/src/VBox/Runtime/tools/RTFTPServer.cpp
r82715 r82723 48 48 #include <iprt/ctype.h> 49 49 #include <iprt/errcore.h> 50 #include <iprt/file.h> 50 51 #include <iprt/getopt.h> 51 52 #include <iprt/initterm.h> … … 191 192 192 193 return VINF_SUCCESS; 194 } 195 196 static DECLCALLBACK(int) onFileGetSize(PRTFTPCALLBACKDATA pData, const char *pcszPath, uint64_t *puSize) 197 { 198 RT_NOREF(pData); 199 200 RTPrintf("Retrieving file size for '%s' ...\n", pcszPath); 201 202 RTFILE hFile; 203 int rc = RTFileOpen(&hFile, pcszPath, 204 RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 205 if (RT_SUCCESS(rc)) 206 { 207 rc = RTFileQuerySize(hFile, puSize); 208 if (RT_SUCCESS(rc)) 209 RTPrintf("File size is: %RU64\n", *puSize); 210 RTFileClose(hFile); 211 } 212 213 return rc; 214 } 215 216 static DECLCALLBACK(int) onFileStat(PRTFTPCALLBACKDATA pData, const char *pcszPath, PRTFSOBJINFO pFsObjInfo) 217 { 218 RT_NOREF(pData); 219 220 RTFILE hFile; 221 int rc = RTFileOpen(&hFile, pcszPath, 222 RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 223 if (RT_SUCCESS(rc)) 224 { 225 rc = RTFileQueryInfo(hFile, pFsObjInfo, RTFSOBJATTRADD_NOTHING); 226 RTFileClose(hFile); 227 } 228 229 return rc; 193 230 } 194 231 … … 337 374 Callbacks.pfnOnUserAuthenticate = onUserAuthenticate; 338 375 Callbacks.pfnOnUserDisconnect = onUserDisonnect; 376 Callbacks.pfnOnFileGetSize = onFileGetSize; 377 Callbacks.pfnOnFileStat = onFileStat; 339 378 Callbacks.pfnOnPathSetCurrent = onPathSetCurrent; 340 379 Callbacks.pfnOnPathGetCurrent = onPathGetCurrent; 341 380 Callbacks.pfnOnPathUp = onPathUp; 342 Callbacks.pfnOnList = onList;343 381 Callbacks.pfnOnList = onList; 344 382
Note:
See TracChangeset
for help on using the changeset viewer.