📄 ftpfs.c
字号:
} if (s == nStreams) { /* * Reallocate stream pointers * Guard against the case where realloc() returns NULL. */ struct ftpStream **np; np = realloc (ftpStreams, ++nStreams * sizeof *ftpStreams); if (np == NULL) { eno = ENOMEM; } else { ftpStreams = np; } } } if (eno == 0) { fsp = ftpStreams[s] = malloc (sizeof (struct ftpStream)); rtems_semaphore_release (ftp_mutex); sema_obtained = FALSE; if (fsp == NULL) { eno = ENOMEM; } else { iop->data0 = s; iop->data1 = fsp; fsp->ctrl_socket = -1; /* mark, that sockets not yet created */ fsp->port_socket = -1; fsp->data_socket = -1; fsp->eof_reached = FALSE; } } if (eno == 0) { /* * Create the socket for control connection */ if ((fsp->ctrl_socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) { eno = ENOMEM; } } if (eno == 0) { /* * Set the destination to the FTP server * port on the remote machine. */ memset(&(fsp->farCtrlAddress),sizeof(fsp->farCtrlAddress),0); fsp->farCtrlAddress.sin_family = AF_INET; if (*hostname == '\0') { fsp->farCtrlAddress.sin_addr.s_addr = rtems_bsdnet_bootp_server_address.s_addr; } else if (1 != inet_aton(hostname,&(fsp->farCtrlAddress.sin_addr))) { struct hostent *hent; struct hostent *gethostbyname(const char *name); hent = gethostbyname(hostname); if (hent != NULL) { bcopy(hent->h_addr, (char *)(&(fsp->farCtrlAddress.sin_addr)), sizeof(fsp->farCtrlAddress.sin_addr)); } else { eno = ENOENT; } } if (eno == 0) { fsp->farCtrlAddress.sin_port = htons (FTP_PORT_NUM); fsp->farCtrlAddress.sin_len = sizeof(fsp->farCtrlAddress); if (0 > connect(fsp->ctrl_socket, (struct sockaddr *)&(fsp->farCtrlAddress), sizeof(fsp->farCtrlAddress))) { eno = ENOENT; } } if (eno == 0) { /* * fetch IP address of interface used */ memset(&(fsp->myCtrlAddress),sizeof(fsp->myCtrlAddress),0); fsp->myCtrlAddress.sin_family = AF_INET; fsp->myCtrlAddress.sin_addr.s_addr = INADDR_ANY; fsp->myCtrlAddress.sin_port = 0; fsp->myCtrlAddress.sin_len = sizeof(fsp->myDataAddress); sockaddr_size = sizeof(fsp->myCtrlAddress); if (0 > getsockname(fsp->ctrl_socket, (struct sockaddr *)&(fsp->myCtrlAddress), &sockaddr_size)) { eno = ENOMEM; } } } if (eno == 0) { /* * now we should get a connect message from the FTP server */ eno = rtems_ftp_get_message(fsp,&msg_tmp); if ((eno == 0) && (msg_tmp != FTP_REPLY_CONNECT)) { eno = ENOENT; } } if (eno == 0) { /* * send user ID to server * NOTE: the following lines will be executed in order * and will be aborted whenever an error occures... (see your ANSI C book) */ if ((0 > send(fsp->ctrl_socket,FTP_USER_CMD,strlen(FTP_USER_CMD),0)) || (0 > send(fsp->ctrl_socket,uname, strlen(uname), 0)) || (0 > send(fsp->ctrl_socket,"\n", 1, 0))) { eno = EIO; } } if (eno == 0) { /* * now we should get a request for the password or a login... */ eno = rtems_ftp_get_message(fsp,&msg_tmp); if (eno == 0) { if (msg_tmp == FTP_REPLY_PASSREQ) { /* * send password to server */#ifdef DEBUG_OUT write(1,FTP_PASS_CMD,strlen(FTP_PASS_CMD)); write(1,upass, strlen(upass) ); write(1,"\n", 1 );#endif if ((0 > send(fsp->ctrl_socket,FTP_PASS_CMD,strlen(FTP_PASS_CMD),0)) || (0 > send(fsp->ctrl_socket,upass, strlen(upass), 0)) || (0 > send(fsp->ctrl_socket,"\n", 1, 0))) { eno = EIO; } /* * at least now a login reply should come up... * this is checked some lines downwards the code */ if (eno == 0) { eno = rtems_ftp_get_message(fsp,&msg_tmp); } } } } if (eno == 0) { /* * check for a login reply. this should be present now... */ if (msg_tmp != FTP_REPLY_LOGIN) { eno = EACCES; /* pseudo for wrong user/pass */ } } if (eno == 0) { /* * set binary mode for all transfers */#ifdef DEBUG_OUT write(1,FTP_BINARY_CMD,strlen(FTP_BINARY_CMD)); write(1,"\n", 1 );#endif if ((0 > send(fsp->ctrl_socket,FTP_BINARY_CMD,strlen(FTP_BINARY_CMD),0)) || (0 > send(fsp->ctrl_socket,"\n", 1, 0))) { eno = EIO; } else { eno = rtems_ftp_get_message(fsp,&msg_tmp); } } if (eno == 0) { /* * check for a "BINARY TYPE command successful" reply */ if (msg_tmp != FTP_REPLY_SUCCESS) { eno = EIO; } } if (eno == 0) { /* * create and bind socket for data connection */ if ((fsp->port_socket = socket (AF_INET, SOCK_STREAM, 0)) < 0) { eno = ENOMEM; } else { memset(&(fsp->myDataAddress),sizeof(fsp->myDataAddress),0); fsp->myDataAddress.sin_family = AF_INET; fsp->myDataAddress.sin_addr.s_addr = INADDR_ANY; fsp->myDataAddress.sin_port = 0; /* unique port will be assigned */ fsp->myDataAddress.sin_len = sizeof(fsp->myDataAddress); if (0 > bind(fsp->port_socket, (struct sockaddr *)&(fsp->myDataAddress), sizeof(fsp->myDataAddress))) { eno = EBUSY; } else { /* * fetch port number of data socket */ memset(&(fsp->myDataAddress),sizeof(fsp->myDataAddress),0); fsp->myDataAddress.sin_family = AF_INET; fsp->myDataAddress.sin_addr.s_addr = INADDR_ANY; fsp->myDataAddress.sin_port = 0; fsp->myDataAddress.sin_len = sizeof(fsp->myDataAddress); sockaddr_size = sizeof(fsp->myDataAddress); if (0 > getsockname(fsp->port_socket, (struct sockaddr *)&(fsp->myDataAddress), &sockaddr_size)) { eno = ENOMEM; } } } } if (eno == 0) { /* * propagate data connection port to server */ my_ip = ntohl(fsp->myCtrlAddress.sin_addr.s_addr); my_port = ntohs(fsp->myDataAddress.sin_port); sprintf(port_buffer,"%s%u,%u,%u,%u,%u,%u\n", FTP_PORT_CMD, (my_ip >> 24) & 0x00ff, (my_ip >> 16) & 0x00ff, (my_ip >> 8) & 0x00ff, (my_ip >> 0) & 0x00ff, (my_port>> 8) & 0x00ff, (my_port>> 0) & 0x00ff);#ifdef DEBUG_OUT write(1,port_buffer,strlen(port_buffer));#endif if (0 > send(fsp->ctrl_socket,port_buffer,strlen(port_buffer),0)) { eno = EIO; } else { eno = rtems_ftp_get_message(fsp,&msg_tmp); } } if (eno == 0) { /* * check for a "PORT command successful" reply */ if (msg_tmp != FTP_REPLY_SUCCESS) { eno = EBUSY; } } /* * prepare port socket to listen for incoming connections */ if (eno == 0) { if (0 > listen(fsp->port_socket,1)) { eno = EBUSY; } } if (eno == 0) { /* * send retrive/store command with filename */ if (is_write) {#ifdef DEBUG_OUT write(1,FTP_STOR_CMD,strlen(FTP_STOR_CMD)); write(1,filename ,strlen(filename) ); write(1,"\n",1);#endif if ((0 > send(fsp->ctrl_socket,FTP_STOR_CMD,strlen(FTP_STOR_CMD),0)) || (0 > send(fsp->ctrl_socket,filename, strlen(filename), 0)) || (0 > send(fsp->ctrl_socket,"\n", 1, 0))) { eno = EIO; } } else {#ifdef DEBUG_OUT write(1,FTP_RETR_CMD,strlen(FTP_RETR_CMD)); write(1,filename ,strlen(filename) ); write(1,"\n",1);#endif if ((0 > send(fsp->ctrl_socket,FTP_RETR_CMD,strlen(FTP_RETR_CMD),0)) || (0 > send(fsp->ctrl_socket,filename, strlen(filename), 0)) || (0 > send(fsp->ctrl_socket,"\n", 1, 0))) { eno = EIO; } } }#if 1 if (eno == 0) { eno = rtems_ftp_get_message(fsp,&msg_tmp); } if (eno == 0) { /* * check for a "OPENING binary connection" reply */ if (msg_tmp != FTP_REPLY_OPENCONN) { eno = EACCES; } }#endif /* * wait for connect on data connection * FIXME: this should become a select instead with a timeout */ if (eno == 0) { sockaddr_size = sizeof(fsp->farDataAddress); fsp->data_socket = accept(fsp->port_socket, (struct sockaddr *)&(fsp->farDataAddress), &sockaddr_size); if (0 > fsp->data_socket) { eno = EIO; } } /* * FIXME: check, that fardataAddr is really from our ftp server */ /* * clean up temp strings... */ if (uname != NULL) { free(uname); uname = NULL; } if (upass != NULL) { free(upass); upass = NULL; } if (hostname != NULL) { free(hostname); hostname = NULL; } if (filename != NULL) { free(filename); filename = NULL; } /* * close part socket, no longer needed */ if (fsp->port_socket != -1) { close(fsp->port_socket); fsp->port_socket = -1; } /* * if error, clean up everything */ if (eno != 0) { if (fsp != NULL) { /* * check and close ctrl/data connection */ if (fsp->data_socket != -1) { close(fsp->data_socket); fsp->data_socket = -1; } if (fsp->ctrl_socket != -1) { close(fsp->ctrl_socket); fsp->ctrl_socket = -1; } /* * free ftpStream structure */ ftpStreams[s] = NULL; free(fsp); fsp = NULL; } } /* * return sema, if still occupied */ if (sema_obtained) { rtems_semaphore_release (ftp_mutex); sema_obtained = FALSE; }#if 0 if (eno != 0) { set_errno_and_return_minus_one(eno); } return 0;#else return eno;#endif}/* * Read from a FTP stream */ssize_t rtems_ftp_read( rtems_libio_t *iop, void *buffer, unsigned32 count){ int eno = 0; struct ftpStream *fsp; size_t want_cnt; ssize_t rd_cnt; int msg_tmp; fsp = iop->data1; want_cnt = count; /* * check, that data connection present */ if (eno == 0) { if ((fsp == NULL) || (fsp->data_socket < 0)) { eno = EBADF; } } /* * perform read from data socket * read multiple junks, if smaller than wanted */ while ((eno == 0) && (want_cnt > 0) && !(fsp->eof_reached) ) { rd_cnt = read(fsp->data_socket,buffer,want_cnt); if (rd_cnt > 0) { buffer += rd_cnt; want_cnt -= rd_cnt; } else { eno = rtems_ftp_get_message(fsp,&msg_tmp); fsp->eof_reached = TRUE; if ((eno == 0) && (msg_tmp != FTP_REPLY_TFERCMPL)) { eno = EIO; } if (rd_cnt < 0) { eno = EIO; } } } if (eno != 0) { set_errno_and_return_minus_one(eno); } return count - want_cnt;}ssize_t rtems_ftp_write( rtems_libio_t *iop, const void *buffer, unsigned32 count){ int eno = EIO; struct ftpStream *fsp; size_t want_cnt; ssize_t wr_cnt; int msg_tmp; fsp = iop->data1; want_cnt = count; /* * check, that data connection present */ if (eno == 0) { if ((fsp == NULL) || (fsp->data_socket < 0)) { eno = EBADF; } } /* * perform write to data socket */ if (eno == 0) { wr_cnt = write(fsp->data_socket,buffer,want_cnt); if (wr_cnt > 0) { buffer += wr_cnt; want_cnt -= wr_cnt; } else { eno = rtems_ftp_get_message(fsp,&msg_tmp); if ((eno == 0) && (msg_tmp != FTP_REPLY_TFERCMPL)) { eno = EIO; } if (wr_cnt < 0) { eno = EIO; } } } if (eno != 0) { set_errno_and_return_minus_one(eno); } return count - want_cnt;}/* * Close a FTP stream */int rtems_ftp_close( rtems_libio_t *iop){ int s = iop->data0; struct ftpStream *fsp = iop->data1; /* * close ctrl/data connection, if needed */ if (fsp->data_socket >= 0) { close(fsp->data_socket); fsp->data_socket = -1; } if (fsp->ctrl_socket >= 0) { close(fsp->ctrl_socket); fsp->ctrl_socket = -1; } /* * free any used space... */ rtems_semaphore_obtain (ftp_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); free (ftpStreams[s]); ftpStreams[s] = NULL; rtems_semaphore_release (ftp_mutex); return 0;}rtems_device_driver rtems_ftp_control( rtems_device_major_number major, rtems_device_minor_number minor, void *pargp){ return RTEMS_NOT_CONFIGURED;}/* * Dummy version to let fopen(xxxx,"w") work properly. */static int rtems_ftp_ftruncate( rtems_libio_t *iop, off_t count){ return 0;}rtems_filesystem_node_types_t rtems_ftp_node_type( rtems_filesystem_location_info_t *pathloc /* IN */){ return RTEMS_FILESYSTEM_MEMORY_FILE;}rtems_filesystem_operations_table rtems_ftp_ops = { rtems_ftp_eval_path, /* eval_path */ rtems_ftp_evaluate_for_make, /* evaluate_for_make */ NULL, /* link */ NULL, /* unlink */ rtems_ftp_node_type, /* node_type */ NULL, /* mknod */ NULL, /* chown */ NULL, /* freenodinfo */ NULL, /* mount */ rtems_ftp_mount_me, /* initialize */ NULL, /* unmount */ NULL, /* fsunmount */ NULL, /* utime, */ NULL, /* evaluate_link */ NULL, /* symlink */ NULL, /* readlin */}; rtems_filesystem_file_handlers_r rtems_ftp_handlers = { rtems_ftp_open, /* open */ rtems_ftp_close, /* close */ rtems_ftp_read, /* read */ rtems_ftp_write, /* write */ NULL, /* ioctl */ NULL, /* lseek */ NULL, /* fstat */ NULL, /* fchmod */ rtems_ftp_ftruncate, /* ftruncate */ NULL, /* fpathconf */ NULL, /* fsync */ NULL, /* fdatasync */ NULL, /* fcntl */ NULL /* rmnod */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -