Manual pages: mcmcdiffmceditmcview

root/src/vfs/local/local.c

/* [previous][next][first][last][top][bottom][index][help]  */

DEFINITIONS

This source file includes following definitions.
  1. local_open
  2. local_opendir
  3. local_readdir
  4. local_closedir
  5. local_stat
  6. local_lstat
  7. local_chmod
  8. local_chown
  9. local_fgetflags
  10. local_fsetflags
  11. local_utime
  12. local_readlink
  13. local_unlink
  14. local_symlink
  15. local_write
  16. local_rename
  17. local_chdir
  18. local_mknod
  19. local_link
  20. local_mkdir
  21. local_rmdir
  22. local_getlocalcopy
  23. local_ungetlocalcopy
  24. local_which
  25. local_read
  26. local_close
  27. local_errno
  28. local_fstat
  29. local_lseek
  30. local_nothingisopen
  31. vfs_init_localfs

   1 /*
   2    Virtual File System: local file system.
   3 
   4    Copyright (C) 1995-2025
   5    Free Software Foundation, Inc.
   6 
   7    This file is part of the Midnight Commander.
   8 
   9    The Midnight Commander is free software: you can redistribute it
  10    and/or modify it under the terms of the GNU General Public License as
  11    published by the Free Software Foundation, either version 3 of the License,
  12    or (at your option) any later version.
  13 
  14    The Midnight Commander is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18 
  19    You should have received a copy of the GNU General Public License
  20    along with this program.  If not, see <https://www.gnu.org/licenses/>.
  21  */
  22 
  23 /**
  24  * \file
  25  * \brief Source: local FS
  26  */
  27 
  28 #include <config.h>
  29 
  30 #include <errno.h>
  31 #include <sys/types.h>
  32 #include <unistd.h>
  33 #include <stdio.h>
  34 #include <string.h>
  35 #ifdef ENABLE_EXT2FS_ATTR
  36 #include <e2p/e2p.h>  // fgetflags(), fsetflags()
  37 #endif
  38 
  39 #include "lib/global.h"
  40 
  41 #include "lib/vfs/xdirentry.h"  // vfs_s_subclass
  42 #include "lib/vfs/utilvfs.h"
  43 
  44 #include "local.h"
  45 
  46 /*** global variables ****************************************************************************/
  47 
  48 /*** file scope macro definitions ****************************************************************/
  49 
  50 /*** file scope type declarations ****************************************************************/
  51 
  52 /*** forward declarations (file scope functions) *************************************************/
  53 
  54 /*** file scope variables ************************************************************************/
  55 
  56 static struct vfs_s_subclass local_subclass;
  57 static struct vfs_class *vfs_local_ops = VFS_CLASS (&local_subclass);
  58 
  59 /* --------------------------------------------------------------------------------------------- */
  60 /*** file scope functions ************************************************************************/
  61 /* --------------------------------------------------------------------------------------------- */
  62 
  63 static void *
  64 local_open (const vfs_path_t *vpath, int flags, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
  65 {
  66     int *local_info;
  67     int fd;
  68     const char *path;
  69 
  70     path = vfs_path_get_last_path_str (vpath);
  71     fd = open (path, NO_LINEAR (flags), mode);
  72     if (fd == -1)
  73         return 0;
  74 
  75     local_info = g_new (int, 1);
  76     *local_info = fd;
  77 
  78     return local_info;
  79 }
  80 
  81 /* --------------------------------------------------------------------------------------------- */
  82 
  83 static void *
  84 local_opendir (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
  85 {
  86     DIR *dir = NULL;
  87 
  88     const char *path = vfs_path_get_last_path_str (vpath);
  89 
  90     /* According to POSIX, `opendir` and `readdir` can't return EINTR (unlike `closedir`).
  91      *
  92      * Unfortunately, in practice, at least `readdir` is known to return EINTR on Linux >= 5.1 on
  93      * networked filesystems such as CIFS. Networked FUSE-based systems appear to be affected as
  94      * well. What's worse is that when you retry `readdir`, the file list still comes out empty.
  95      *
  96      * So our only option seems to be to try `readdir` immediately after `opendir` and use
  97      * `rewinddir` if successful, otherwise reopen the directory, which usually leads to correct
  98      * file listing.
  99      *
 100      * However, this has caused problems on FUSE-based systems that do not properly implement
 101      * `rewinddir` in the past. No silver bullet...
 102      */
 103     while (dir == NULL)
 104     {
 105         dir = opendir (path);
 106         if (dir == NULL)
 107             return NULL;
 108 
 109         if (readdir (dir) == NULL && errno == EINTR)
 110         {
 111             closedir (dir);
 112             dir = NULL;
 113         }
 114         else
 115             rewinddir (dir);
 116     }
 117 
 118     DIR **local_info = (DIR **) g_new (DIR *, 1);
 119     *local_info = dir;
 120 
 121     return local_info;
 122 }
 123 
 124 /* --------------------------------------------------------------------------------------------- */
 125 
 126 static struct vfs_dirent *
 127 local_readdir (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 128 {
 129     struct dirent *d;
 130     unsigned char type;
 131 
 132     d = readdir (*(DIR **) data);
 133 
 134     if (d == NULL)
 135         return NULL;
 136 
 137 #ifdef HAVE_STRUCT_DIRENT_D_TYPE
 138     type = d->d_type;
 139 #else
 140     type = DT_UNKNOWN;
 141 #endif
 142 
 143     return vfs_dirent_init (NULL, d->d_name, d->d_ino, type);
 144 }
 145 
 146 /* --------------------------------------------------------------------------------------------- */
 147 
 148 static int
 149 local_closedir (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 150 {
 151     int i;
 152 
 153     i = closedir (*(DIR **) data);
 154     g_free (data);
 155     return i;
 156 }
 157 
 158 /* --------------------------------------------------------------------------------------------- */
 159 
 160 static int
 161 local_stat (const vfs_path_t *vpath, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 162 {
 163     const char *path;
 164 
 165     path = vfs_path_get_last_path_str (vpath);
 166     return stat (path, buf);
 167 }
 168 
 169 /* --------------------------------------------------------------------------------------------- */
 170 
 171 static int
 172 local_lstat (const vfs_path_t *vpath, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 173 {
 174     const char *path;
 175 
 176     path = vfs_path_get_last_path_str (vpath);
 177 #ifndef HAVE_STATLSTAT
 178     return lstat (path, buf);
 179 #else
 180     return statlstat (path, buf);
 181 #endif
 182 }
 183 
 184 /* --------------------------------------------------------------------------------------------- */
 185 
 186 static int
 187 local_chmod (const vfs_path_t *vpath, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 188 {
 189     const char *path;
 190 
 191     path = vfs_path_get_last_path_str (vpath);
 192     return chmod (path, mode);
 193 }
 194 
 195 /* --------------------------------------------------------------------------------------------- */
 196 
 197 static int
 198 local_chown (const vfs_path_t *vpath, uid_t owner, gid_t group)
     /* [previous][next][first][last][top][bottom][index][help]  */
 199 {
 200     const char *path;
 201 
 202     path = vfs_path_get_last_path_str (vpath);
 203     return chown (path, owner, group);
 204 }
 205 
 206 /* --------------------------------------------------------------------------------------------- */
 207 
 208 #ifdef ENABLE_EXT2FS_ATTR
 209 
 210 static int
 211 local_fgetflags (const vfs_path_t *vpath, unsigned long *flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 212 {
 213     const char *path;
 214 
 215     path = vfs_path_get_last_path_str (vpath);
 216     return fgetflags (path, flags);
 217 }
 218 
 219 /* --------------------------------------------------------------------------------------------- */
 220 
 221 static int
 222 local_fsetflags (const vfs_path_t *vpath, unsigned long flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 223 {
 224     const char *path;
 225 
 226     path = vfs_path_get_last_path_str (vpath);
 227     return fsetflags (path, flags);
 228 }
 229 
 230 #endif
 231 
 232 /* --------------------------------------------------------------------------------------------- */
 233 
 234 static int
 235 local_utime (const vfs_path_t *vpath, mc_timesbuf_t *times)
     /* [previous][next][first][last][top][bottom][index][help]  */
 236 {
 237     return vfs_utime (vfs_path_get_last_path_str (vpath), times);
 238 }
 239 
 240 /* --------------------------------------------------------------------------------------------- */
 241 
 242 static int
 243 local_readlink (const vfs_path_t *vpath, char *buf, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 244 {
 245     const char *path;
 246 
 247     path = vfs_path_get_last_path_str (vpath);
 248     return readlink (path, buf, size);
 249 }
 250 
 251 /* --------------------------------------------------------------------------------------------- */
 252 
 253 static int
 254 local_unlink (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 255 {
 256     const char *path;
 257 
 258     path = vfs_path_get_last_path_str (vpath);
 259     return unlink (path);
 260 }
 261 
 262 /* --------------------------------------------------------------------------------------------- */
 263 
 264 static int
 265 local_symlink (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 266 {
 267     const char *path1, *path2;
 268 
 269     path1 = vfs_path_get_last_path_str (vpath1);
 270     path2 = vfs_path_get_last_path_str (vpath2);
 271     return symlink (path1, path2);
 272 }
 273 
 274 /* --------------------------------------------------------------------------------------------- */
 275 
 276 static ssize_t
 277 local_write (void *data, const char *buf, size_t nbyte)
     /* [previous][next][first][last][top][bottom][index][help]  */
 278 {
 279     int fd;
 280     int n;
 281 
 282     if (data == NULL)
 283         return (-1);
 284 
 285     fd = *(int *) data;
 286 
 287     while ((n = write (fd, buf, nbyte)) == -1)
 288     {
 289 #ifdef EAGAIN
 290         if (errno == EAGAIN)
 291             continue;
 292 #endif
 293 #ifdef EINTR
 294         if (errno == EINTR)
 295             continue;
 296 #endif
 297         break;
 298     }
 299 
 300     return n;
 301 }
 302 
 303 /* --------------------------------------------------------------------------------------------- */
 304 
 305 static int
 306 local_rename (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 307 {
 308     const char *path1, *path2;
 309 
 310     path1 = vfs_path_get_last_path_str (vpath1);
 311     path2 = vfs_path_get_last_path_str (vpath2);
 312     return rename (path1, path2);
 313 }
 314 
 315 /* --------------------------------------------------------------------------------------------- */
 316 
 317 static int
 318 local_chdir (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 319 {
 320     const char *path;
 321 
 322     path = vfs_path_get_last_path_str (vpath);
 323     return chdir (path);
 324 }
 325 
 326 /* --------------------------------------------------------------------------------------------- */
 327 
 328 static int
 329 local_mknod (const vfs_path_t *vpath, mode_t mode, dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help]  */
 330 {
 331     const char *path;
 332 
 333     path = vfs_path_get_last_path_str (vpath);
 334     return mknod (path, mode, dev);
 335 }
 336 
 337 /* --------------------------------------------------------------------------------------------- */
 338 
 339 static int
 340 local_link (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 341 {
 342     const char *path1, *path2;
 343 
 344     path1 = vfs_path_get_last_path_str (vpath1);
 345     path2 = vfs_path_get_last_path_str (vpath2);
 346     return link (path1, path2);
 347 }
 348 
 349 /* --------------------------------------------------------------------------------------------- */
 350 
 351 static int
 352 local_mkdir (const vfs_path_t *vpath, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 353 {
 354     const char *path;
 355 
 356     path = vfs_path_get_last_path_str (vpath);
 357     return mkdir (path, mode);
 358 }
 359 
 360 /* --------------------------------------------------------------------------------------------- */
 361 
 362 static int
 363 local_rmdir (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 364 {
 365     const char *path;
 366 
 367     path = vfs_path_get_last_path_str (vpath);
 368     return rmdir (path);
 369 }
 370 
 371 /* --------------------------------------------------------------------------------------------- */
 372 
 373 static vfs_path_t *
 374 local_getlocalcopy (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 375 {
 376     return vfs_path_clone (vpath);
 377 }
 378 
 379 /* --------------------------------------------------------------------------------------------- */
 380 
 381 static int
 382 local_ungetlocalcopy (const vfs_path_t *vpath, const vfs_path_t *local, gboolean has_changed)
     /* [previous][next][first][last][top][bottom][index][help]  */
 383 {
 384     (void) vpath;
 385     (void) local;
 386     (void) has_changed;
 387 
 388     return 0;
 389 }
 390 
 391 /* --------------------------------------------------------------------------------------------- */
 392 
 393 static int
 394 local_which (struct vfs_class *me, const char *path)
     /* [previous][next][first][last][top][bottom][index][help]  */
 395 {
 396     (void) me;
 397     (void) path;
 398 
 399     return 0;  // Every path which other systems do not like is expected to be ours
 400 }
 401 
 402 /* --------------------------------------------------------------------------------------------- */
 403 /*** public functions ****************************************************************************/
 404 /* --------------------------------------------------------------------------------------------- */
 405 
 406 ssize_t
 407 local_read (void *data, char *buffer, size_t count)
     /* [previous][next][first][last][top][bottom][index][help]  */
 408 {
 409     int n;
 410     int fd;
 411 
 412     if (data == NULL)
 413         return (-1);
 414 
 415     fd = *(int *) data;
 416 
 417     while ((n = read (fd, buffer, count)) == -1)
 418     {
 419 #ifdef EAGAIN
 420         if (errno == EAGAIN)
 421             continue;
 422 #endif
 423 #ifdef EINTR
 424         if (errno == EINTR)
 425             continue;
 426 #endif
 427         return (-1);
 428     }
 429 
 430     return n;
 431 }
 432 
 433 /* --------------------------------------------------------------------------------------------- */
 434 
 435 int
 436 local_close (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 437 {
 438     int fd;
 439 
 440     if (data == NULL)
 441         return (-1);
 442 
 443     fd = *(int *) data;
 444     g_free (data);
 445     return close (fd);
 446 }
 447 
 448 /* --------------------------------------------------------------------------------------------- */
 449 
 450 int
 451 local_errno (struct vfs_class *me)
     /* [previous][next][first][last][top][bottom][index][help]  */
 452 {
 453     (void) me;
 454     return errno;
 455 }
 456 
 457 /* --------------------------------------------------------------------------------------------- */
 458 
 459 int
 460 local_fstat (void *data, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 461 {
 462     int fd = *(int *) data;
 463 
 464     return fstat (fd, buf);
 465 }
 466 
 467 /* --------------------------------------------------------------------------------------------- */
 468 
 469 off_t
 470 local_lseek (void *data, off_t offset, int whence)
     /* [previous][next][first][last][top][bottom][index][help]  */
 471 {
 472     int fd = *(int *) data;
 473 
 474     return lseek (fd, offset, whence);
 475 }
 476 
 477 /* --------------------------------------------------------------------------------------------- */
 478 
 479 static gboolean
 480 local_nothingisopen (vfsid id)
     /* [previous][next][first][last][top][bottom][index][help]  */
 481 {
 482     (void) id;
 483 
 484     return TRUE;
 485 }
 486 
 487 /* --------------------------------------------------------------------------------------------- */
 488 
 489 void
 490 vfs_init_localfs (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 491 {
 492     // NULLize vfs_s_subclass members
 493     memset (&local_subclass, 0, sizeof (local_subclass));
 494 
 495     vfs_init_class (vfs_local_ops, "localfs", VFSF_LOCAL, NULL);
 496     vfs_local_ops->which = local_which;
 497     vfs_local_ops->open = local_open;
 498     vfs_local_ops->close = local_close;
 499     vfs_local_ops->read = local_read;
 500     vfs_local_ops->write = local_write;
 501     vfs_local_ops->opendir = local_opendir;
 502     vfs_local_ops->readdir = local_readdir;
 503     vfs_local_ops->closedir = local_closedir;
 504     vfs_local_ops->stat = local_stat;
 505     vfs_local_ops->lstat = local_lstat;
 506     vfs_local_ops->fstat = local_fstat;
 507     vfs_local_ops->chmod = local_chmod;
 508     vfs_local_ops->chown = local_chown;
 509 #ifdef ENABLE_EXT2FS_ATTR
 510     vfs_local_ops->fgetflags = local_fgetflags;
 511     vfs_local_ops->fsetflags = local_fsetflags;
 512 #endif
 513     vfs_local_ops->utime = local_utime;
 514     vfs_local_ops->readlink = local_readlink;
 515     vfs_local_ops->symlink = local_symlink;
 516     vfs_local_ops->link = local_link;
 517     vfs_local_ops->unlink = local_unlink;
 518     vfs_local_ops->rename = local_rename;
 519     vfs_local_ops->chdir = local_chdir;
 520     vfs_local_ops->ferrno = local_errno;
 521     vfs_local_ops->lseek = local_lseek;
 522     vfs_local_ops->mknod = local_mknod;
 523     vfs_local_ops->getlocalcopy = local_getlocalcopy;
 524     vfs_local_ops->ungetlocalcopy = local_ungetlocalcopy;
 525     vfs_local_ops->mkdir = local_mkdir;
 526     vfs_local_ops->rmdir = local_rmdir;
 527     vfs_local_ops->nothingisopen = local_nothingisopen;
 528     vfs_register_class (vfs_local_ops);
 529 }
 530 
 531 /* --------------------------------------------------------------------------------------------- */

/* [previous][next][first][last][top][bottom][index][help]  */