Ticket #3406: sftpfs_internal-cleanup.diff
File sftpfs_internal-cleanup.diff, 20.0 KB (added by sand, 8 years ago) |
---|
-
src/vfs/sftpfs/internal.c
diff --git a/src/vfs/sftpfs/internal.c b/src/vfs/sftpfs/internal.c index 5377b66e5..69a8684ad 100644
a b 30 30 #include "lib/global.h" 31 31 #include "lib/util.h" 32 32 33 #include "src/filemanager/ioblksize.h" /* IO_BUFSIZE */ 34 33 35 #include "internal.h" 34 36 37 38 35 39 /*** global variables ****************************************************************************/ 36 40 37 41 GString *sftpfs_filename_buffer = NULL; 38 42 39 43 /*** file scope macro definitions ****************************************************************/ 44 #define mc_return_val_if_error_and_free(mcerror, mcvalue, to_free) \ 45 do { \ 46 if (mcerror != NULL && *mcerror != NULL) \ 47 { \ 48 if (to_free != NULL) \ 49 g_free(to_free); \ 50 return mcvalue; \ 51 } \ 52 } while (0) 53 54 #define _is_sftp_proto_error(super_data, res, libssh_errno) \ 55 ((res == LIBSSH2_ERROR_SFTP_PROTOCOL) && \ 56 (libssh2_sftp_last_error((super_data)->sftp_session) == libssh_errno)) 40 57 41 58 /*** file scope type declarations ****************************************************************/ 42 59 43 60 /*** file scope variables ************************************************************************/ 44 61 45 62 /*** file scope functions ************************************************************************/ 63 64 static int 65 _waitsocket_or_error(sftpfs_super_data_t *super_data, int res, 66 GError ** mcerror, void *to_free) 67 { 68 if (res != LIBSSH2_ERROR_EAGAIN) 69 { 70 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 71 if (to_free != NULL) 72 g_free(to_free); 73 return -1; 74 } 75 76 sftpfs_waitsocket (super_data, mcerror); 77 mc_return_val_if_error_and_free (mcerror, -1, to_free); 78 79 return 0; 80 } 81 46 82 /* --------------------------------------------------------------------------------------------- */ 83 static int 84 _sftpfs_op_init(sftpfs_super_data_t ** super_data, 85 const vfs_path_element_t ** path_element, 86 const vfs_path_t * vpath, GError ** mcerror) 87 { 88 struct vfs_s_super *super; 89 90 mc_return_val_if_error (mcerror, -1); 91 92 *path_element = vfs_path_get_by_index (vpath, -1); 93 94 if (vfs_s_get_path (vpath, &super, 0) == NULL) 95 return -1; 96 97 if (super == NULL) 98 return -1; 99 100 *super_data = (sftpfs_super_data_t *) super->data; 101 if ((*super_data)->sftp_session == NULL) 102 return -1; 103 104 return 0; 105 } 106 107 /* --------------------------------------------------------------------------------------------- */ 108 109 static int 110 _sftpfs_stat (sftpfs_super_data_t ** super_data, 111 const vfs_path_element_t ** path_element, 112 const vfs_path_t * vpath, GError ** mcerror, const int stat_type, 113 LIBSSH2_SFTP_ATTRIBUTES *attrs) 114 { 115 int res; 116 117 if (_sftpfs_op_init(super_data, path_element, vpath, mcerror) != 0) 118 return -1; 119 120 do 121 { 122 const char *fixfname; 123 124 fixfname = sftpfs_fix_filename ((*path_element)->path); 125 126 res = libssh2_sftp_stat_ex ((*super_data)->sftp_session, fixfname, 127 sftpfs_filename_buffer->len, 128 stat_type, attrs); 129 130 if (res >= 0) 131 break; 132 133 if (_is_sftp_proto_error(*super_data, res, 134 LIBSSH2_FX_PERMISSION_DENIED)) 135 return EACCES; 136 137 if (_is_sftp_proto_error(*super_data, res, LIBSSH2_FX_NO_SUCH_FILE)) 138 return ENOENT; 139 140 if (_waitsocket_or_error(*super_data, res, mcerror, NULL) != 0) 141 return -1; 142 } 143 while (res == LIBSSH2_ERROR_EAGAIN); 144 145 return res; 146 } 147 148 /* --------------------------------------------------------------------------------------------- */ 149 150 static void 151 _sftpfs_attr_to_buf(struct stat *buf, LIBSSH2_SFTP_ATTRIBUTES *attrs) 152 { 153 if ((attrs->flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0) 154 { 155 buf->st_uid = attrs->uid; 156 buf->st_gid = attrs->gid; 157 } 158 159 if ((attrs->flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0) 160 { 161 buf->st_atime = attrs->atime; 162 buf->st_mtime = attrs->mtime; 163 buf->st_ctime = attrs->mtime; 164 } 165 166 if ((attrs->flags & LIBSSH2_SFTP_ATTR_SIZE) != 0) 167 buf->st_size = attrs->filesize; 168 169 if ((attrs->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0) 170 buf->st_mode = attrs->permissions; 171 172 /* patch or segfault here */ 173 buf->st_blksize = IO_BUFSIZE; 174 buf->st_blocks = 1 + ((buf->st_size - 1) / buf->st_blksize); 175 } 47 176 48 177 /* --------------------------------------------------------------------------------------------- */ 49 178 /*** public functions ****************************************************************************/ … … sftpfs_ssherror_to_gliberror (sftpfs_super_data_t * super_data, int libssh_errno 65 194 mc_return_if_error (mcerror); 66 195 67 196 libssh2_session_last_error (super_data->session, &err, &err_len, 1); 68 mc_propagate_error (mcerror, libssh_errno, "%s", err); 197 if (libssh_errno == LIBSSH2_ERROR_SFTP_PROTOCOL && 198 super_data->sftp_session != NULL) 199 { 200 mc_propagate_error (mcerror, libssh_errno, "%s %lu", err, 201 libssh2_sftp_last_error(super_data->sftp_session)); 202 } else { 203 mc_propagate_error (mcerror, libssh_errno, "%s", err); 204 } 69 205 g_free (err); 70 206 } 71 207 … … sftpfs_waitsocket (sftpfs_super_data_t * super_data, GError ** mcerror) 132 268 int 133 269 sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) 134 270 { 135 struct vfs_s_super *super;271 const vfs_path_element_t *path_element; 136 272 sftpfs_super_data_t *super_data; 137 273 LIBSSH2_SFTP_ATTRIBUTES attrs; 138 274 int res; 139 const vfs_path_element_t *path_element;140 141 mc_return_val_if_error (mcerror, -1);142 143 path_element = vfs_path_get_by_index (vpath, -1);144 145 if (vfs_s_get_path (vpath, &super, 0) == NULL)146 return -1;147 148 if (super == NULL)149 return -1;150 151 super_data = (sftpfs_super_data_t *) super->data;152 if (super_data->sftp_session == NULL)153 return -1;154 155 do156 {157 const char *fixfname;158 159 fixfname = sftpfs_fix_filename (path_element->path);160 275 161 res = libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, 162 sftpfs_filename_buffer->len, LIBSSH2_SFTP_LSTAT, &attrs); 163 if (res >= 0) 164 break; 276 res = _sftpfs_stat (&super_data, &path_element, vpath, mcerror, 277 LIBSSH2_SFTP_LSTAT, &attrs); 165 278 166 if (res != LIBSSH2_ERROR_EAGAIN) 167 { 168 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 169 return -1; 170 } 279 if (res == -1 || res == EACCES || res == ENOENT) 280 return res; 171 281 172 sftpfs_waitsocket (super_data, mcerror); 173 mc_return_val_if_error (mcerror, -1); 174 } 175 while (res == LIBSSH2_ERROR_EAGAIN); 176 177 if ((attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0) 178 { 179 buf->st_uid = attrs.uid; 180 buf->st_gid = attrs.gid; 181 } 182 183 if ((attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0) 184 { 185 buf->st_atime = attrs.atime; 186 buf->st_mtime = attrs.mtime; 187 buf->st_ctime = attrs.mtime; 188 } 189 190 if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0) 191 buf->st_size = attrs.filesize; 192 193 if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0) 194 buf->st_mode = attrs.permissions; 282 _sftpfs_attr_to_buf(buf, &attrs); 195 283 196 284 return 0; 197 285 } … … sftpfs_lstat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) 209 297 int 210 298 sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) 211 299 { 212 struct vfs_s_super *super;300 const vfs_path_element_t *path_element; 213 301 sftpfs_super_data_t *super_data; 214 302 LIBSSH2_SFTP_ATTRIBUTES attrs; 215 303 int res; 216 const vfs_path_element_t *path_element;217 218 mc_return_val_if_error (mcerror, -1);219 220 path_element = vfs_path_get_by_index (vpath, -1);221 222 if (vfs_s_get_path (vpath, &super, 0) == NULL)223 return -1;224 225 if (super == NULL)226 return -1;227 304 228 super_data = (sftpfs_super_data_t *) super->data; 229 if (super_data->sftp_session == NULL) 230 return -1; 231 232 do 233 { 234 const char *fixfname; 235 236 fixfname = sftpfs_fix_filename (path_element->path); 305 res = _sftpfs_stat (&super_data, &path_element, vpath, mcerror, 306 LIBSSH2_SFTP_STAT, &attrs); 237 307 238 res = 239 libssh2_sftp_stat_ex (super_data->sftp_session, 240 fixfname, sftpfs_filename_buffer->len, LIBSSH2_SFTP_STAT, &attrs); 241 if (res >= 0) 242 break; 243 244 if (res != LIBSSH2_ERROR_EAGAIN) 245 { 246 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 247 return -1; 248 } 249 250 sftpfs_waitsocket (super_data, mcerror); 251 mc_return_val_if_error (mcerror, -1); 252 } 253 while (res == LIBSSH2_ERROR_EAGAIN); 308 if (res == -1 || res == EACCES || res == ENOENT) 309 return res; 254 310 255 311 buf->st_nlink = 1; 256 if ((attrs.flags & LIBSSH2_SFTP_ATTR_UIDGID) != 0)257 {258 buf->st_uid = attrs.uid;259 buf->st_gid = attrs.gid;260 }261 262 if ((attrs.flags & LIBSSH2_SFTP_ATTR_ACMODTIME) != 0)263 {264 buf->st_atime = attrs.atime;265 buf->st_mtime = attrs.mtime;266 buf->st_ctime = attrs.mtime;267 }268 312 269 if ((attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) != 0) 270 buf->st_size = attrs.filesize; 271 272 if ((attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) != 0) 273 buf->st_mode = attrs.permissions; 313 _sftpfs_attr_to_buf(buf, &attrs); 274 314 275 315 return 0; 276 316 } … … sftpfs_stat (const vfs_path_t * vpath, struct stat *buf, GError ** mcerror) 289 329 int 290 330 sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mcerror) 291 331 { 292 struct vfs_s_super *super;332 const vfs_path_element_t *path_element; 293 333 sftpfs_super_data_t *super_data; 294 334 int res; 295 const vfs_path_element_t *path_element;296 297 mc_return_val_if_error (mcerror, -1);298 335 299 path_element = vfs_path_get_by_index (vpath, -1); 300 301 if (vfs_s_get_path (vpath, &super, 0) == NULL) 302 return -1; 303 304 if (super == NULL) 305 return -1; 306 307 super_data = (sftpfs_super_data_t *) super->data; 308 if (super_data->sftp_session == NULL) 336 if (_sftpfs_op_init(&super_data, &path_element, vpath, mcerror) != 0) 309 337 return -1; 310 338 311 339 do … … sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mce 314 342 315 343 fixfname = sftpfs_fix_filename (path_element->path); 316 344 317 res = libssh2_sftp_readlink (super_data->sftp_session, fixfname, buf, size); 345 res = libssh2_sftp_readlink (super_data->sftp_session, fixfname, 346 buf, size); 318 347 if (res >= 0) 319 348 break; 320 349 321 if (res != LIBSSH2_ERROR_EAGAIN) 322 { 323 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 350 if (_waitsocket_or_error(super_data, res,mcerror, NULL) != 0) 324 351 return -1; 325 }326 327 sftpfs_waitsocket (super_data, mcerror);328 mc_return_val_if_error (mcerror, -1);329 352 } 330 353 while (res == LIBSSH2_ERROR_EAGAIN); 331 354 … … sftpfs_readlink (const vfs_path_t * vpath, char *buf, size_t size, GError ** mce 345 368 int 346 369 sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** mcerror) 347 370 { 348 struct vfs_s_super *super;349 sftpfs_super_data_t *super_data;350 371 const vfs_path_element_t *path_element1; 351 372 const vfs_path_element_t *path_element2; 373 sftpfs_super_data_t *super_data; 352 374 char *tmp_path; 353 375 int res; 354 376 355 mc_return_val_if_error (mcerror, -1); 356 357 path_element2 = vfs_path_get_by_index (vpath2, -1); 358 359 if (vfs_s_get_path (vpath2, &super, 0) == NULL) 360 return -1; 361 362 if (super == NULL) 363 return -1; 364 365 super_data = (sftpfs_super_data_t *) super->data; 366 if (super_data->sftp_session == NULL) 377 if (_sftpfs_op_init(&super_data, &path_element2, vpath2, mcerror) != 0) 367 378 return -1; 368 379 369 380 tmp_path = g_strdup_printf ("%c%s", PATH_SEP, path_element2->path); … … sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** 375 386 376 387 fixfname = sftpfs_fix_filename (path_element1->path); 377 388 378 res = 379 libssh2_sftp_symlink_ex (super_data->sftp_session, 380 fixfname, 381 sftpfs_filename_buffer->len, tmp_path, strlen (tmp_path), 382 LIBSSH2_SFTP_SYMLINK); 389 res = libssh2_sftp_symlink_ex (super_data->sftp_session, fixfname, 390 sftpfs_filename_buffer->len, tmp_path, 391 strlen (tmp_path), LIBSSH2_SFTP_SYMLINK); 383 392 if (res >= 0) 384 393 break; 385 394 386 if (res != LIBSSH2_ERROR_EAGAIN) 387 { 388 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 389 g_free (tmp_path); 390 return -1; 391 } 392 393 sftpfs_waitsocket (super_data, mcerror); 394 if (mcerror != NULL && *mcerror != NULL) 395 { 396 g_free (tmp_path); 395 if (_waitsocket_or_error(super_data, res,mcerror, tmp_path) != 0) 397 396 return -1; 398 }399 397 } 400 398 while (res == LIBSSH2_ERROR_EAGAIN); 401 399 g_free (tmp_path); … … sftpfs_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** 416 414 int 417 415 sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror) 418 416 { 419 struct vfs_s_super *super;417 const vfs_path_element_t *path_element; 420 418 sftpfs_super_data_t *super_data; 421 419 LIBSSH2_SFTP_ATTRIBUTES attrs; 422 420 int res; 423 const vfs_path_element_t *path_element;424 421 425 mc_return_val_if_error (mcerror, -1); 422 res = _sftpfs_stat(&super_data, &path_element, vpath, mcerror, 423 LIBSSH2_SFTP_LSTAT, &attrs); 426 424 427 path_element = vfs_path_get_by_index (vpath, -1); 425 if (res == -1 || res == EACCES || res == ENOENT) 426 return res; 428 427 429 if (vfs_s_get_path (vpath, &super, 0) == NULL) 430 return -1; 431 432 if (super == NULL) 433 return -1; 434 435 super_data = (sftpfs_super_data_t *) super->data; 436 if (super_data->sftp_session == NULL) 437 return -1; 428 attrs.permissions = mode; 438 429 439 430 do 440 431 { … … sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror) 443 434 fixfname = sftpfs_fix_filename (path_element->path); 444 435 445 436 res = libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, 446 sftpfs_filename_buffer->len, LIBSSH2_SFTP_LSTAT, &attrs); 437 sftpfs_filename_buffer->len, 438 LIBSSH2_SFTP_SETSTAT, &attrs); 447 439 if (res >= 0) 448 440 break; 449 441 450 if ( res != LIBSSH2_ERROR_EAGAIN)442 if (_is_sftp_proto_error(super_data, res, LIBSSH2_FX_FAILURE)) 451 443 { 452 sftpfs_ssherror_to_gliberror (super_data, res, mcerror);453 return -1;444 res = 0; /* need something like ftpfs_ignore_chattr_errors */ 445 break; 454 446 } 455 447 456 sftpfs_waitsocket (super_data, mcerror); 457 mc_return_val_if_error (mcerror, -1); 458 } 459 while (res == LIBSSH2_ERROR_EAGAIN); 448 if (_is_sftp_proto_error(super_data, res, LIBSSH2_FX_NO_SUCH_FILE)) 449 return ENOENT; 460 450 461 attrs.permissions = mode; 462 463 do 464 { 465 const char *fixfname; 466 467 fixfname = sftpfs_fix_filename (path_element->path); 468 469 res = libssh2_sftp_stat_ex (super_data->sftp_session, fixfname, 470 sftpfs_filename_buffer->len, LIBSSH2_SFTP_SETSTAT, &attrs); 471 if (res >= 0) 472 break; 473 else if (res != LIBSSH2_ERROR_EAGAIN) 474 { 475 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 451 if (_waitsocket_or_error(super_data, res,mcerror, NULL) != 0) 476 452 return -1; 477 }478 479 sftpfs_waitsocket (super_data, mcerror);480 mc_return_val_if_error (mcerror, -1);481 453 } 482 454 while (res == LIBSSH2_ERROR_EAGAIN); 455 483 456 return res; 484 457 } 485 458 … … sftpfs_chmod (const vfs_path_t * vpath, mode_t mode, GError ** mcerror) 495 468 int 496 469 sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror) 497 470 { 498 struct vfs_s_super *super;471 const vfs_path_element_t *path_element; 499 472 sftpfs_super_data_t *super_data; 500 473 int res; 501 const vfs_path_element_t *path_element;502 474 503 mc_return_val_if_error (mcerror, -1); 504 505 path_element = vfs_path_get_by_index (vpath, -1); 506 507 if (vfs_s_get_path (vpath, &super, 0) == NULL) 508 return -1; 509 510 if (super == NULL) 511 return -1; 512 513 super_data = (sftpfs_super_data_t *) super->data; 514 if (super_data->sftp_session == NULL) 475 if (_sftpfs_op_init(&super_data, &path_element, vpath, mcerror) != 0) 515 476 return -1; 516 477 517 478 do … … sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror) 520 481 521 482 fixfname = sftpfs_fix_filename (path_element->path); 522 483 523 res = 524 libssh2_sftp_unlink_ex (super_data->sftp_session, fixfname, 525 sftpfs_filename_buffer->len); 484 res = libssh2_sftp_unlink_ex (super_data->sftp_session, fixfname, 485 sftpfs_filename_buffer->len); 526 486 if (res >= 0) 527 487 break; 528 488 529 if (res != LIBSSH2_ERROR_EAGAIN) 530 { 531 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 489 if (_waitsocket_or_error(super_data, res,mcerror, NULL) != 0) 532 490 return -1; 533 }534 535 sftpfs_waitsocket (super_data, mcerror);536 mc_return_val_if_error (mcerror, -1);537 491 } 538 492 while (res == LIBSSH2_ERROR_EAGAIN); 539 493 … … sftpfs_unlink (const vfs_path_t * vpath, GError ** mcerror) 553 507 int 554 508 sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** mcerror) 555 509 { 556 struct vfs_s_super *super;557 sftpfs_super_data_t *super_data;558 510 const vfs_path_element_t *path_element1; 559 511 const vfs_path_element_t *path_element2; 512 sftpfs_super_data_t *super_data; 560 513 char *tmp_path; 561 514 int res; 562 515 563 mc_return_val_if_error (mcerror, -1); 564 path_element2 = vfs_path_get_by_index (vpath2, -1); 565 566 if (vfs_s_get_path (vpath2, &super, 0) == NULL) 567 return -1; 568 569 if (super == NULL) 570 return -1; 571 572 super_data = (sftpfs_super_data_t *) super->data; 573 if (super_data->sftp_session == NULL) 516 if (_sftpfs_op_init(&super_data, &path_element2, vpath2, mcerror) != 0) 574 517 return -1; 575 518 576 519 tmp_path = g_strdup_printf ("%c%s", PATH_SEP, path_element2->path); … … sftpfs_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2, GError ** m 582 525 583 526 fixfname = sftpfs_fix_filename (path_element1->path); 584 527 585 res = libssh2_sftp_rename_ex 586 (super_data->sftp_session,587 fixfname,588 sftpfs_filename_buffer->len, tmp_path, strlen (tmp_path), LIBSSH2_SFTP_SYMLINK); 528 res = libssh2_sftp_rename_ex (super_data->sftp_session, fixfname, 529 sftpfs_filename_buffer->len, tmp_path, 530 strlen (tmp_path), LIBSSH2_SFTP_SYMLINK); 531 589 532 if (res >= 0) 590 533 break; 591 534 592 if (res != LIBSSH2_ERROR_EAGAIN) 593 { 594 sftpfs_ssherror_to_gliberror (super_data, res, mcerror); 595 g_free (tmp_path); 535 if (_waitsocket_or_error(super_data, res,mcerror, tmp_path) != 0) 596 536 return -1; 597 }598 599 sftpfs_waitsocket (super_data, mcerror);600 if (mcerror != NULL && *mcerror != NULL)601 {602 g_free (tmp_path);603 return -1;604 }605 537 } 606 538 while (res == LIBSSH2_ERROR_EAGAIN); 607 539 g_free (tmp_path);