Changeset 82687 in vbox
- Timestamp:
- Jan 9, 2020 10:45:36 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 3 edited
-
include/iprt/ftp.h (modified) (2 diffs)
-
src/VBox/Runtime/generic/ftp-server.cpp (modified) (15 diffs)
-
src/VBox/Runtime/tools/RTFTPServer.cpp (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/ftp.h
r82673 r82687 133 133 134 134 /** 135 * Structure for maintaining a FTP server client state. 136 */ 137 typedef struct RTFTPSERVERCLIENTSTATE 138 { 139 /** Timestamp (in ms) of last command issued by the client. */ 140 uint64_t tsLastCmdMs; 141 } RTFTPSERVERCLIENTSTATE; 142 /** Pointer to a FTP server client state. */ 143 typedef RTFTPSERVERCLIENTSTATE *PRTFTPSERVERCLIENTSTATE; 144 145 /** 146 * Structure for storing FTP server callback data. 147 */ 148 typedef struct RTFTPCALLBACKDATA 149 { 150 /** Pointer to the client state. */ 151 PRTFTPSERVERCLIENTSTATE pClient; 152 /** Saved user pointer. */ 153 void *pvUser; 154 /** Size (in bytes) of data at user pointer. */ 155 size_t cbUser; 156 } RTFTPCALLBACKDATA; 157 /** Pointer to FTP server callback data. */ 158 typedef RTFTPCALLBACKDATA *PRTFTPCALLBACKDATA; 159 160 /** 161 * Function callback table for the FTP server implementation. 162 * 163 * All callbacks are optional and therefore can be NULL. 164 */ 165 typedef struct RTFTPSERVERCALLBACKS 166 { 167 /** User pointer to data. Optional and can be NULL. */ 168 void *pvUser; 169 /** Size (in bytes) of user data pointing at. Optional and can be 0. */ 170 size_t cbUser; 171 DECLCALLBACKMEMBER(int, pfnOnUserConnect)(PRTFTPCALLBACKDATA pData, const char *pcszUser); 172 DECLCALLBACKMEMBER(int, pfnOnUserAuthenticate)(PRTFTPCALLBACKDATA pData, const char *pcszUser, const char *pcszPassword); 173 DECLCALLBACKMEMBER(int, pfnOnUserDisconnect)(PRTFTPCALLBACKDATA pData); 174 DECLCALLBACKMEMBER(int, pfnOnPathSetCurrent)(PRTFTPCALLBACKDATA pData, const char *pcszCWD); 175 DECLCALLBACKMEMBER(int, pfnOnPathGetCurrent)(PRTFTPCALLBACKDATA pData, char *pszPWD, size_t cbPWD); 176 DECLCALLBACKMEMBER(int, pfnOnList)(PRTFTPCALLBACKDATA pData, void **ppvData, size_t *pcbData); 177 } RTFTPSERVERCALLBACKS, *PRTFTPSERVERCALLBACKS; 178 /** Pointer to a FTP server callback data table. */ 179 typedef RTFTPSERVERCALLBACKS *PRTFTPSERVERCALLBACKS; 180 181 /** 135 182 * Creates a FTP server instance. 136 183 * … … 140 187 * If NULL or empty string the server is bound to all interfaces. 141 188 * @param uPort The port for creating a listening socket. 142 * @param p cszPathRoot Root path of the FTP server serving.189 * @param pCallbacks Callback table to use. 143 190 */ 144 191 RTR3DECL(int) RTFTPServerCreate(PRTFTPSERVER phFTPServer, const char *pcszAddress, uint16_t uPort, 145 const char *pcszPathRoot);192 PRTFTPSERVERCALLBACKS pCallbacks); 146 193 147 194 /** -
trunk/src/VBox/Runtime/generic/ftp-server.cpp
r82678 r82687 40 40 *********************************************************************************************************************************/ 41 41 #define LOG_GROUP RTLOGGROUP_FTP 42 #include <iprt/asm.h> 42 43 #include <iprt/assert.h> 43 44 #include <iprt/errcore.h> … … 45 46 #include <iprt/mem.h> 46 47 #include <iprt/log.h> 48 #include <iprt/path.h> 47 49 #include <iprt/poll.h> 48 50 #include <iprt/socket.h> … … 63 65 { 64 66 /** Magic value. */ 65 uint32_t u32Magic; 67 uint32_t u32Magic; 68 /** Callback table. */ 69 RTFTPSERVERCALLBACKS Callbacks; 66 70 /** Pointer to TCP server instance. */ 67 PRTTCPSERVER pTCPServer; 71 PRTTCPSERVER pTCPServer; 72 /** Number of currently connected clients. */ 73 uint32_t cClients; 68 74 } RTFTPSERVERINTERNAL; 69 75 /** Pointer to an internal FTP server instance. */ … … 136 142 137 143 /** 138 * Structure for maintaining an internal FTP server client state.139 */ 140 typedef struct RTFTPSERVERCLIENT STATE144 * Structure for maintaining an internal FTP server client. 145 */ 146 typedef struct RTFTPSERVERCLIENT 141 147 { 142 148 /** Pointer to internal server state. */ 143 PRTFTPSERVERINTERNAL pServer;149 PRTFTPSERVERINTERNAL pServer; 144 150 /** Socket handle the client is bound to. */ 145 RTSOCKET hSocket; 146 } RTFTPSERVERCLIENTSTATE; 151 RTSOCKET hSocket; 152 /** Actual client state. */ 153 RTFTPSERVERCLIENTSTATE State; 154 } RTFTPSERVERCLIENT; 147 155 /** Pointer to an internal FTP server client state. */ 148 typedef RTFTPSERVERCLIENT STATE *PRTFTPSERVERCLIENTSTATE;156 typedef RTFTPSERVERCLIENT *PRTFTPSERVERCLIENT; 149 157 150 158 /** Function pointer declaration for a specific FTP server command handler. */ 151 typedef DECLCALLBACK(int) FNRTFTPSERVERCMD(PRTFTPSERVERCLIENT STATEpClient);159 typedef DECLCALLBACK(int) FNRTFTPSERVERCMD(PRTFTPSERVERCLIENT pClient); 152 160 /** Pointer to a FNRTFTPSERVERCMD(). */ 153 161 typedef FNRTFTPSERVERCMD *PFNRTFTPSERVERCMD; 162 163 /** Handles a FTP server callback with no arguments and returns. */ 164 #define RTFTPSERVER_HANDLE_CALLBACK_RET(a_Name) \ 165 do \ 166 { \ 167 PRTFTPSERVERCALLBACKS pCallbacks = &pClient->pServer->Callbacks; \ 168 if (pCallbacks->a_Name) \ 169 { \ 170 RTFTPCALLBACKDATA Data = { &pClient->State, pCallbacks->pvUser, pCallbacks->cbUser }; \ 171 return pCallbacks->a_Name(&Data); \ 172 } \ 173 } while (0) 174 175 /** Handles a FTP server callback with arguments and returns. */ 176 #define RTFTPSERVER_HANDLE_CALLBACK_VA_RET(a_Name, ...) \ 177 do \ 178 { \ 179 PRTFTPSERVERCALLBACKS pCallbacks = &pClient->pServer->Callbacks; \ 180 if (pCallbacks->a_Name) \ 181 { \ 182 RTFTPCALLBACKDATA Data = { &pClient->State, pCallbacks->pvUser, pCallbacks->cbUser }; \ 183 return pCallbacks->a_Name(&Data, __VA_ARGS__); \ 184 } \ 185 } while (0) 154 186 155 187 /** … … 207 239 208 240 209 static int rtFTPServerSendReplyRc(PRTFTPSERVERCLIENTSTATE pClient, RTFTPSERVER_REPLY enmReply) 241 /********************************************************************************************************************************* 242 * Protocol Functions * 243 *********************************************************************************************************************************/ 244 245 /** 246 * Replies a (three digit) reply code back to the client. 247 * 248 * @returns VBox status code. 249 * @param pClient Client to reply to. 250 * @param enmReply Reply code to send. 251 */ 252 static int rtFTPServerSendReplyRc(PRTFTPSERVERCLIENT pClient, RTFTPSERVER_REPLY enmReply) 210 253 { 211 254 char szReply[32]; … … 215 258 } 216 259 217 static int rtFTPServerSendReplyStr(PRTFTPSERVERCLIENTSTATE pClient, const char *pcszStr) 260 /** 261 * Replies a string back to the client. 262 * 263 * @returns VBox status code. 264 * @param pClient Client to reply to. 265 * @param pcszStr String to reply. 266 */ 267 static int rtFTPServerSendReplyStr(PRTFTPSERVERCLIENT pClient, const char *pcszStr) 218 268 { 219 269 char *pszReply; … … 229 279 } 230 280 231 static int rtFTPServerLookupUser(PRTFTPSERVERCLIENTSTATE pClient, const char *pcszUser) 232 { 233 RT_NOREF(pClient, pcszUser); 234 235 LogFunc(("User='%s'\n", pcszUser)); 236 237 return VINF_SUCCESS; /** @todo Implement lookup. */ 238 } 239 240 static int rtFTPServerAuthenticate(PRTFTPSERVERCLIENTSTATE pClient, const char *pcszUser, const char *pcszPassword) 241 { 242 RT_NOREF(pClient, pcszUser, pcszPassword); 243 244 LogFunc(("User='%s', Password='%s'\n", pcszUser, pcszPassword)); 245 246 return VINF_SUCCESS; /** @todo Implement authentication. */ 247 } 248 249 static int rtFTPServerHandleABOR(PRTFTPSERVERCLIENTSTATE pClient) 250 { 251 RT_NOREF(pClient); 252 253 /** @todo Anything to do here? */ 254 return VINF_SUCCESS; 255 } 256 257 static int rtFTPServerHandleCDUP(PRTFTPSERVERCLIENTSTATE pClient) 258 { 259 RT_NOREF(pClient); 260 261 /** @todo Anything to do here? */ 262 return VINF_SUCCESS; 263 } 264 265 static int rtFTPServerHandleCWD(PRTFTPSERVERCLIENTSTATE pClient) 266 { 267 RT_NOREF(pClient); 268 269 /** @todo Anything to do here? */ 270 return VINF_SUCCESS; 271 } 272 273 static int rtFTPServerHandleLIST(PRTFTPSERVERCLIENTSTATE pClient) 274 { 275 RT_NOREF(pClient); 276 277 /** @todo Anything to do here? */ 278 return VINF_SUCCESS; 279 } 280 281 static int rtFTPServerHandleMODE(PRTFTPSERVERCLIENTSTATE pClient) 282 { 283 RT_NOREF(pClient); 284 285 /** @todo Anything to do here? */ 286 return VINF_SUCCESS; 287 } 288 289 static int rtFTPServerHandleNOOP(PRTFTPSERVERCLIENTSTATE pClient) 290 { 291 RT_NOREF(pClient); 292 293 /** @todo Anything to do here? */ 294 return VINF_SUCCESS; 295 } 296 297 static int rtFTPServerHandlePORT(PRTFTPSERVERCLIENTSTATE pClient) 298 { 299 RT_NOREF(pClient); 300 301 /** @todo Anything to do here? */ 302 return VINF_SUCCESS; 303 } 304 305 static int rtFTPServerHandlePWD(PRTFTPSERVERCLIENTSTATE pClient) 306 { 307 RT_NOREF(pClient); 308 309 /** @todo Anything to do here? */ 310 return VINF_SUCCESS; 311 } 312 313 static int rtFTPServerHandleQUIT(PRTFTPSERVERCLIENTSTATE pClient) 314 { 315 RT_NOREF(pClient); 316 317 /** @todo Anything to do here? */ 318 return VINF_SUCCESS; 319 } 320 321 static int rtFTPServerHandleRETR(PRTFTPSERVERCLIENTSTATE pClient) 322 { 323 RT_NOREF(pClient); 324 325 /** @todo Anything to do here? */ 326 return VINF_SUCCESS; 327 } 328 329 static int rtFTPServerHandleRGET(PRTFTPSERVERCLIENTSTATE pClient) 330 { 331 RT_NOREF(pClient); 332 333 /** @todo Anything to do here? */ 334 return VINF_SUCCESS; 335 } 336 337 static int rtFTPServerHandleSTAT(PRTFTPSERVERCLIENTSTATE pClient) 338 { 339 RT_NOREF(pClient); 340 341 /** @todo Anything to do here? */ 342 return VINF_SUCCESS; 343 } 344 345 static int rtFTPServerHandleSYST(PRTFTPSERVERCLIENTSTATE pClient) 281 /** 282 * Looks up an user account. 283 * 284 * @returns VBox status code, or VERR_NOT_FOUND if user has not been found. 285 * @param pClient Client to look up user for. 286 * @param pcszUser User name to look up. 287 */ 288 static int rtFTPServerLookupUser(PRTFTPSERVERCLIENT pClient, const char *pcszUser) 289 { 290 RTFTPSERVER_HANDLE_CALLBACK_VA_RET(pfnOnUserConnect, pcszUser); 291 292 return VERR_NOT_FOUND; 293 } 294 295 /** 296 * Handles the actual client authentication. 297 * 298 * @returns VBox status code, or VERR_ACCESS_DENIED if authentication failed. 299 * @param pClient Client to authenticate. 300 * @param pcszUser User name to authenticate with. 301 * @param pcszPassword Password to authenticate with. 302 */ 303 static int rtFTPServerAuthenticate(PRTFTPSERVERCLIENT pClient, const char *pcszUser, const char *pcszPassword) 304 { 305 RTFTPSERVER_HANDLE_CALLBACK_VA_RET(pfnOnUserAuthenticate, pcszUser, pcszPassword); 306 307 return VERR_ACCESS_DENIED; 308 } 309 310 311 /********************************************************************************************************************************* 312 * Command Protocol Handlers * 313 *********************************************************************************************************************************/ 314 315 static int rtFTPServerHandleABOR(PRTFTPSERVERCLIENT pClient) 316 { 317 RT_NOREF(pClient); 318 319 /** @todo Anything to do here? */ 320 return VINF_SUCCESS; 321 } 322 323 static int rtFTPServerHandleCDUP(PRTFTPSERVERCLIENT pClient) 324 { 325 RT_NOREF(pClient); 326 327 /** @todo Anything to do here? */ 328 return VINF_SUCCESS; 329 } 330 331 static int rtFTPServerHandleCWD(PRTFTPSERVERCLIENT pClient) 332 { 333 RT_NOREF(pClient); 334 335 /** @todo Anything to do here? */ 336 return VINF_SUCCESS; 337 } 338 339 static int rtFTPServerHandleLIST(PRTFTPSERVERCLIENT pClient) 340 { 341 RT_NOREF(pClient); 342 343 /** @todo Anything to do here? */ 344 return VINF_SUCCESS; 345 } 346 347 static int rtFTPServerHandleMODE(PRTFTPSERVERCLIENT pClient) 348 { 349 RT_NOREF(pClient); 350 351 /** @todo Anything to do here? */ 352 return VINF_SUCCESS; 353 } 354 355 static int rtFTPServerHandleNOOP(PRTFTPSERVERCLIENT pClient) 356 { 357 RT_NOREF(pClient); 358 359 /* Nothing to do here. */ 360 return VINF_SUCCESS; 361 } 362 363 static int rtFTPServerHandlePORT(PRTFTPSERVERCLIENT pClient) 364 { 365 RT_NOREF(pClient); 366 367 /** @todo Anything to do here? */ 368 return VINF_SUCCESS; 369 } 370 371 static int rtFTPServerHandlePWD(PRTFTPSERVERCLIENT pClient) 372 { 373 #if 0 374 char *pszReply; 375 int rc = RTStrAPrintf(&pszReply, "%s\r\n", pClient->szCWD); 376 if (RT_SUCCESS(rc)) 377 { 378 rc = RTTcpWrite(pClient->hSocket, pszReply, strlen(pszReply) + 1); 379 RTStrFree(pszReply); 380 return rc; 381 } 382 383 return VERR_NO_MEMORY; 384 #endif 385 386 RT_NOREF(pClient); 387 return 0; 388 } 389 390 static int rtFTPServerHandleQUIT(PRTFTPSERVERCLIENT pClient) 391 { 392 RT_NOREF(pClient); 393 394 /** @todo Anything to do here? */ 395 return VINF_SUCCESS; 396 } 397 398 static int rtFTPServerHandleRETR(PRTFTPSERVERCLIENT pClient) 399 { 400 RT_NOREF(pClient); 401 402 /** @todo Anything to do here? */ 403 return VINF_SUCCESS; 404 } 405 406 static int rtFTPServerHandleRGET(PRTFTPSERVERCLIENT pClient) 407 { 408 RT_NOREF(pClient); 409 410 /** @todo Anything to do here? */ 411 return VINF_SUCCESS; 412 } 413 414 static int rtFTPServerHandleSTAT(PRTFTPSERVERCLIENT pClient) 415 { 416 RT_NOREF(pClient); 417 418 /** @todo Anything to do here? */ 419 return VINF_SUCCESS; 420 } 421 422 static int rtFTPServerHandleSYST(PRTFTPSERVERCLIENT pClient) 346 423 { 347 424 char szOSInfo[64]; … … 353 430 } 354 431 355 static int rtFTPServerHandleTYPE(PRTFTPSERVERCLIENTSTATE pClient) 356 { 357 RT_NOREF(pClient); 358 359 /** @todo Anything to do here? */ 360 return VINF_SUCCESS; 361 } 362 363 static int rtFTPServerDoLogin(PRTFTPSERVERCLIENTSTATE pClient) 432 static int rtFTPServerHandleTYPE(PRTFTPSERVERCLIENT pClient) 433 { 434 RT_NOREF(pClient); 435 436 /** @todo Anything to do here? */ 437 return VINF_SUCCESS; 438 } 439 440 441 /********************************************************************************************************************************* 442 * Internal server functions * 443 *********************************************************************************************************************************/ 444 445 /** 446 * Handles the client's login procedure. 447 * 448 * @returns VBox status code. 449 * @param pClient Client to handle login procedure for. 450 */ 451 static int rtFTPServerDoLogin(PRTFTPSERVERCLIENT pClient) 364 452 { 365 453 LogFlowFuncEnter(); … … 408 496 } 409 497 410 static int rtFTPServerProcessCommands(PRTFTPSERVERCLIENTSTATE pClient) 498 /** 499 * Main loop for processing client commands. 500 * 501 * @returns VBox status code. 502 * @param pClient Client to process commands for. 503 */ 504 static int rtFTPServerProcessCommands(PRTFTPSERVERCLIENT pClient) 411 505 { 412 506 int rc; … … 417 511 char szCmd[RTFTPSERVER_MAX_CMD_LEN]; 418 512 rc = RTTcpRead(pClient->hSocket, szCmd, sizeof(szCmd), &cbRead); 419 if ( RT_SUCCESS(rc) 420 && strlen(szCmd)) 513 if (RT_SUCCESS(rc)) 421 514 { 515 /* Make sure to terminate the string in any case. */ 516 szCmd[RTFTPSERVER_MAX_CMD_LEN - 1] = '\0'; 517 422 518 /* A tiny bit of sanitation. */ 423 519 RTStrStripL(szCmd); … … 439 535 if (!RTStrICmp(szCmd, g_aCmdMap[i].szCmd)) 440 536 { 537 /* Save timestamp of last command sent. */ 538 pClient->State.tsLastCmdMs = RTTimeMilliTS(); 539 441 540 rc = g_aCmdMap[i].pfnCmd(pClient); 442 541 break; … … 452 551 453 552 if (g_aCmdMap[i].enmCmd == RTFTPSERVER_CMD_QUIT) 553 { 554 RTFTPSERVER_HANDLE_CALLBACK_RET(pfnOnUserDisconnect); 454 555 break; 556 } 455 557 } 456 558 else … … 465 567 } 466 568 467 static DECLCALLBACK(int) rtFTPServerThread(RTSOCKET hSocket, void *pvUser) 569 /** 570 * Resets the client's state. 571 * 572 * @param pState Client state to reset. 573 */ 574 static void rtFTPServerClientStateReset(PRTFTPSERVERCLIENTSTATE pState) 575 { 576 pState->tsLastCmdMs = RTTimeMilliTS(); 577 } 578 579 /** 580 * Per-client thread for serving the server's control connection. 581 * 582 * @returns VBox status code. 583 * @param hSocket Socket handle to use for the control connection. 584 * @param pvUser User-provided arguments. Of type PRTFTPSERVERINTERNAL. 585 */ 586 static DECLCALLBACK(int) rtFTPServerClientThread(RTSOCKET hSocket, void *pvUser) 468 587 { 469 588 PRTFTPSERVERINTERNAL pThis = (PRTFTPSERVERINTERNAL)pvUser; 470 589 RTFTPSERVER_VALID_RETURN(pThis); 471 590 472 RTFTPSERVERCLIENTSTATE ClientState; 473 RT_ZERO(ClientState); 474 475 ClientState.pServer = pThis; 476 ClientState.hSocket = hSocket; 477 478 int rc = rtFTPServerDoLogin(&ClientState); 591 RTFTPSERVERCLIENT Client; 592 RT_ZERO(Client); 593 594 Client.pServer = pThis; 595 Client.hSocket = hSocket; 596 597 rtFTPServerClientStateReset(&Client.State); 598 599 int rc = rtFTPServerDoLogin(&Client); 479 600 if (RT_SUCCESS(rc)) 480 rc = rtFTPServerProcessCommands(&ClientState); 601 { 602 ASMAtomicIncU32(&pThis->cClients); 603 604 rc = rtFTPServerProcessCommands(&Client); 605 606 ASMAtomicDecU32(&pThis->cClients); 607 } 481 608 482 609 return rc; … … 484 611 485 612 RTR3DECL(int) RTFTPServerCreate(PRTFTPSERVER phFTPServer, const char *pcszAddress, uint16_t uPort, 486 const char *pcszPathRoot)613 PRTFTPSERVERCALLBACKS pCallbacks) 487 614 { 488 615 AssertPtrReturn(phFTPServer, VERR_INVALID_POINTER); 489 616 AssertPtrReturn(pcszAddress, VERR_INVALID_POINTER); 490 AssertPtrReturn(pcszPathRoot, VERR_INVALID_POINTER);491 617 AssertReturn (uPort, VERR_INVALID_PARAMETER); 618 AssertPtrReturn(pCallbacks, VERR_INVALID_POINTER); 492 619 493 620 int rc; … … 496 623 if (pThis) 497 624 { 498 pThis->u32Magic = RTFTPSERVER_MAGIC; 625 pThis->u32Magic = RTFTPSERVER_MAGIC; 626 pThis->Callbacks = *pCallbacks; 499 627 500 628 rc = RTTcpServerCreate(pcszAddress, uPort, RTTHREADTYPE_DEFAULT, "ftpsrv", 501 rtFTPServer Thread, pThis /* pvUser */, &pThis->pTCPServer);629 rtFTPServerClientThread, pThis /* pvUser */, &pThis->pTCPServer); 502 630 } 503 631 else -
trunk/src/VBox/Runtime/tools/RTFTPServer.cpp
r82671 r82687 57 57 *********************************************************************************************************************************/ 58 58 /** Set by the signal handler when the FTP server shall be terminated. */ 59 static volatile bool g_fCanceled = false; 59 static volatile bool g_fCanceled = false; 60 static char *g_pszRootDir = NULL; 60 61 61 62 … … 145 146 } 146 147 148 static DECLCALLBACK(int) onUserConnect(PRTFTPCALLBACKDATA pData, const char *pcszUser) 149 { 150 RT_NOREF(pData, pcszUser); 151 152 RTPrintf("User '%s' connected", pcszUser); 153 154 return VINF_SUCCESS; 155 } 156 157 static DECLCALLBACK(int) onUserAuthenticate(PRTFTPCALLBACKDATA pData, const char *pcszUser, const char *pcszPassword) 158 { 159 RT_NOREF(pData, pcszUser, pcszPassword); 160 161 RTPrintf("Authenticating user '%s' ...", pcszUser); 162 163 return VINF_SUCCESS; 164 } 165 166 static DECLCALLBACK(int) onUserDisonnect(PRTFTPCALLBACKDATA pData) 167 { 168 RT_NOREF(pData); 169 170 RTPrintf("User disconnected"); 171 172 return VINF_SUCCESS; 173 } 174 175 static DECLCALLBACK(int) onPathSetCurrent(PRTFTPCALLBACKDATA pData, const char *pcszCWD) 176 { 177 RT_NOREF(pData, pcszCWD); 178 179 RTPrintf("Setting current directory to '%s'\n", pcszCWD); 180 181 return VINF_SUCCESS; 182 } 183 184 static DECLCALLBACK(int) onPathGetCurrent(PRTFTPCALLBACKDATA pData, char *pszPWD, size_t cbPWD) 185 { 186 RT_NOREF(pData, pszPWD, cbPWD); 187 188 return VINF_SUCCESS; 189 } 190 191 static DECLCALLBACK(int) onList(PRTFTPCALLBACKDATA pData, void **ppvData, size_t *pcbData) 192 { 193 RT_NOREF(pData, ppvData, pcbData); 194 195 return VINF_SUCCESS; 196 } 197 147 198 int main(int argc, char **argv) 148 199 { … … 154 205 char szAddress[64] = "localhost"; 155 206 uint16_t uPort = 2121; 156 157 /* By default use the current directory as serving root directory. */158 char szRootDir[RTPATH_MAX];159 rc = RTPathGetCurrent(szRootDir, sizeof(szRootDir));160 if (RT_FAILURE(rc))161 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Retrieving current directory failed: %Rrc", rc);162 207 163 208 /* … … 190 235 case 'p': 191 236 uPort = ValueUnion.u16; 237 break; 238 239 case 'r': 240 g_pszRootDir = RTStrDup(ValueUnion.psz); 192 241 break; 193 242 … … 224 273 } 225 274 275 if (!g_pszRootDir) 276 { 277 char szRootDir[RTPATH_MAX]; 278 279 /* By default use the current directory as serving root directory. */ 280 rc = RTPathGetCurrent(szRootDir, sizeof(szRootDir)); 281 if (RT_FAILURE(rc)) 282 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Retrieving current directory failed: %Rrc", rc); 283 284 g_pszRootDir = RTStrDup(szRootDir); 285 if (!g_pszRootDir) 286 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Allocating current directory failed"); 287 } 288 226 289 /* Install signal handler. */ 227 290 rc = signalHandlerInstall(); … … 231 294 * Create the FTP server instance. 232 295 */ 296 RTFTPSERVERCALLBACKS Callbacks; 297 RT_ZERO(Callbacks); 298 Callbacks.pfnOnUserConnect = onUserConnect; 299 Callbacks.pfnOnUserAuthenticate = onUserAuthenticate; 300 Callbacks.pfnOnUserDisconnect = onUserDisonnect; 301 Callbacks.pfnOnPathSetCurrent = onPathSetCurrent; 302 Callbacks.pfnOnPathGetCurrent = onPathGetCurrent; 303 Callbacks.pfnOnList = onList; 304 233 305 RTFTPSERVER hFTPServer; 234 rc = RTFTPServerCreate(&hFTPServer, szAddress, uPort, szRootDir);306 rc = RTFTPServerCreate(&hFTPServer, szAddress, uPort, &Callbacks); 235 307 if (RT_SUCCESS(rc)) 236 308 { 237 309 RTPrintf("Starting FTP server at %s:%RU16 ...\n", szAddress, uPort); 238 RTPrintf("Root directory is '%s'\n", szRootDir);310 RTPrintf("Root directory is '%s'\n", g_pszRootDir); 239 311 240 312 RTPrintf("Running FTP server ...\n"); … … 264 336 } 265 337 338 RTStrFree(g_pszRootDir); 339 266 340 /* Set rcExit on failure in case we forgot to do so before. */ 267 341 if (RT_FAILURE(rc))
Note:
See TracChangeset
for help on using the changeset viewer.

