static off_t fsp_get_file_size (gftp_request * request, const char *filename) { struct stat st; fsp_protocol_data * lpd; g_return_val_if_fail (request != NULL, GFTP_EFATAL); g_return_val_if_fail (request->protonum == GFTP_FSP_NUM, GFTP_EFATAL); g_return_val_if_fail (filename != NULL, GFTP_EFATAL); lpd = request->protocol_data; g_return_val_if_fail (lpd->fsp != NULL, GFTP_EFATAL); if (fsp_stat (lpd->fsp,filename, &st) != 0) return (GFTP_ERETRYABLE); return (st.st_size); }
static off_t fsp_get_file (gftp_request * request, const char *filename, off_t startsize) { fsp_protocol_data * lpd; struct stat sb; g_return_val_if_fail (request != NULL,GFTP_EFATAL); g_return_val_if_fail (request->protonum == GFTP_FSP_NUM,GFTP_EFATAL); g_return_val_if_fail (filename != NULL, GFTP_EFATAL); lpd = request->protocol_data; g_return_val_if_fail (lpd != NULL,GFTP_EFATAL); g_return_val_if_fail (lpd->fsp != NULL,GFTP_EFATAL); /* CHECK: close prev. opened file, is this needed? */ if(lpd->file != NULL) { fsp_fclose(lpd->file); lpd->file=NULL; } if(fsp_stat(lpd->fsp,filename,&sb)) return (GFTP_ERETRYABLE); if(!S_ISREG(sb.st_mode)) return (GFTP_ERETRYABLE); lpd->file=fsp_fopen(lpd->fsp,filename,"rb"); if (fsp_fseek (lpd->file, startsize, SEEK_SET) == -1) { request->logging_function (gftp_logging_error, request, _("Error: Cannot seek on file %s: %s\n"), filename, g_strerror (errno)); gftp_disconnect (request); return (GFTP_ERETRYABLE); } return (sb.st_size); }
static int fsp_stat_filename (gftp_request * request, const char *filename, mode_t * mode, off_t * filesize) { fsp_protocol_data * lpd; struct stat st; g_return_val_if_fail (request != NULL, GFTP_EFATAL); g_return_val_if_fail (request->protonum == GFTP_FSP_NUM, GFTP_EFATAL); g_return_val_if_fail (filename != NULL, GFTP_EFATAL); lpd = request->protocol_data; g_return_val_if_fail (lpd->fsp != NULL, GFTP_EFATAL); if (fsp_stat (lpd->fsp,filename, &st) != 0) return (GFTP_ERETRYABLE); *mode = st.st_mode; *filesize = st.st_size; return (0); }
static bool get_sorted_dir_mtime(vfs_handle_struct *handle, struct dirsort_privates *data, struct timespec *ret_mtime) { int ret; struct timespec mtime; if (data->fsp) { ret = fsp_stat(data->fsp); mtime = data->fsp->fsp_name->st.st_ex_mtime; } else { ret = SMB_VFS_STAT(handle->conn, data->smb_fname); mtime = data->smb_fname->st.st_ex_mtime; } if (ret == -1) { return false; } *ret_mtime = mtime; return true; }
static void do_fsp(struct connection *conn) { FSP_SESSION *ses; struct stat sb; struct uri *uri = conn->uri; struct auth_entry *auth; unsigned char *host = get_uri_string(uri, URI_HOST); unsigned char *data = get_uri_string(uri, URI_DATA); unsigned short port = (unsigned short)get_uri_port(uri); unsigned char *password = NULL; decode_uri(data); if (uri->passwordlen) { password = get_uri_string(uri, URI_PASSWORD); } else { auth = find_auth(uri); if (auth) password = auth->password; } /* fsp_open_session may not set errno if getaddrinfo fails * https://sourceforge.net/tracker/index.php?func=detail&aid=2036798&group_id=93841&atid=605738 * Try to detect this bug and use an ELinks-specific error * code instead, so that we can display a message anyway. */ errno = 0; ses = fsp_open_session(host, port, password); if (!ses) { if (errno) fsp_error(connection_state_for_errno(errno)); else fsp_error(connection_state(S_FSP_OPEN_SESSION_UNKN)); } /* fsplib 0.8 ABI depends on _FILE_OFFSET_BITS * https://sourceforge.net/tracker/index.php?func=detail&aid=1674729&group_id=93841&atid=605738 * If ELinks and fsplib are using different values of * _FILE_OFFSET_BITS, then they get different definitions of * struct stat, and the st_size stored by fsp_stat is * typically not the same as the st_size read by ELinks. * Fortunately, st_mode seems to have the same offset and size * in both versions of struct stat. * * If all the bytes used by the 32-bit st_size are also used * by the 64-bit st_size, then ELinks may be able to guess * which ones they are, because the current version 2 of FSP * supports only 32-bit file sizes in protocol packets. Begin * by filling struct stat with 0xAA so that it's easier to * detect which bytes fsp_stat has left unchanged. (Only * sb.st_size really needs to be filled, but filling the rest * too helps viewing the data with a debugger.) */ memset(&sb, 0xAA, sizeof(sb)); if (fsp_stat(ses, data, &sb)) fsp_error(connection_state_for_errno(errno)); if (S_ISDIR(sb.st_mode)) { fsp_directory(ses, uri); } else { /* regular file */ char buf[READ_SIZE]; FSP_FILE *file = fsp_fopen(ses, data, "r"); int r; if (!file) { fsp_error(connection_state_for_errno(errno)); } #if SIZEOF_OFF_T >= 8 if (sb.st_size < 0 || sb.st_size > 0xFFFFFFFF) { /* Probably a _FILE_OFFSET_BITS mismatch as * described above. Try to detect which half * of st_size is the real size. This may * depend on the endianness of the processor * and on the padding in struct stat. */ if ((sb.st_size & 0xFFFFFFFF00000000ULL) == 0xAAAAAAAA00000000ULL) sb.st_size = sb.st_size & 0xFFFFFFFF; else if ((sb.st_size & 0xFFFFFFFF) == 0xAAAAAAAA) sb.st_size = (sb.st_size >> 32) & 0xFFFFFFFF; else /* Can't figure it out. */ sb.st_size = 1; } #endif /* Send filesize */ fprintf(stderr, "%" OFF_PRINT_FORMAT "\n", (off_print_T) sb.st_size); fclose(stderr); while ((r = fsp_fread(buf, 1, READ_SIZE, file)) > 0) { int off = 0; while (r) { int w = safe_write(STDOUT_FILENO, buf + off, r); if (w == -1) goto out; off += w; r -= w; } } out: fsp_fclose(file); fsp_close_session(ses); exit(0); }