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 
 131     d = readdir (*(DIR **) data);
 132 
 133     return (d != NULL ? vfs_dirent_init (NULL, d->d_name, d->d_ino) : NULL);
 134 }
 135 
 136 /* --------------------------------------------------------------------------------------------- */
 137 
 138 static int
 139 local_closedir (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 140 {
 141     int i;
 142 
 143     i = closedir (*(DIR **) data);
 144     g_free (data);
 145     return i;
 146 }
 147 
 148 /* --------------------------------------------------------------------------------------------- */
 149 
 150 static int
 151 local_stat (const vfs_path_t *vpath, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 152 {
 153     const char *path;
 154 
 155     path = vfs_path_get_last_path_str (vpath);
 156     return stat (path, buf);
 157 }
 158 
 159 /* --------------------------------------------------------------------------------------------- */
 160 
 161 static int
 162 local_lstat (const vfs_path_t *vpath, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 163 {
 164     const char *path;
 165 
 166     path = vfs_path_get_last_path_str (vpath);
 167 #ifndef HAVE_STATLSTAT
 168     return lstat (path, buf);
 169 #else
 170     return statlstat (path, buf);
 171 #endif
 172 }
 173 
 174 /* --------------------------------------------------------------------------------------------- */
 175 
 176 static int
 177 local_chmod (const vfs_path_t *vpath, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 178 {
 179     const char *path;
 180 
 181     path = vfs_path_get_last_path_str (vpath);
 182     return chmod (path, mode);
 183 }
 184 
 185 /* --------------------------------------------------------------------------------------------- */
 186 
 187 static int
 188 local_chown (const vfs_path_t *vpath, uid_t owner, gid_t group)
     /* [previous][next][first][last][top][bottom][index][help]  */
 189 {
 190     const char *path;
 191 
 192     path = vfs_path_get_last_path_str (vpath);
 193     return chown (path, owner, group);
 194 }
 195 
 196 /* --------------------------------------------------------------------------------------------- */
 197 
 198 #ifdef ENABLE_EXT2FS_ATTR
 199 
 200 static int
 201 local_fgetflags (const vfs_path_t *vpath, unsigned long *flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 202 {
 203     const char *path;
 204 
 205     path = vfs_path_get_last_path_str (vpath);
 206     return fgetflags (path, flags);
 207 }
 208 
 209 /* --------------------------------------------------------------------------------------------- */
 210 
 211 static int
 212 local_fsetflags (const vfs_path_t *vpath, unsigned long flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 213 {
 214     const char *path;
 215 
 216     path = vfs_path_get_last_path_str (vpath);
 217     return fsetflags (path, flags);
 218 }
 219 
 220 #endif
 221 
 222 /* --------------------------------------------------------------------------------------------- */
 223 
 224 static int
 225 local_utime (const vfs_path_t *vpath, mc_timesbuf_t *times)
     /* [previous][next][first][last][top][bottom][index][help]  */
 226 {
 227     return vfs_utime (vfs_path_get_last_path_str (vpath), times);
 228 }
 229 
 230 /* --------------------------------------------------------------------------------------------- */
 231 
 232 static int
 233 local_readlink (const vfs_path_t *vpath, char *buf, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 234 {
 235     const char *path;
 236 
 237     path = vfs_path_get_last_path_str (vpath);
 238     return readlink (path, buf, size);
 239 }
 240 
 241 /* --------------------------------------------------------------------------------------------- */
 242 
 243 static int
 244 local_unlink (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 245 {
 246     const char *path;
 247 
 248     path = vfs_path_get_last_path_str (vpath);
 249     return unlink (path);
 250 }
 251 
 252 /* --------------------------------------------------------------------------------------------- */
 253 
 254 static int
 255 local_symlink (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 256 {
 257     const char *path1, *path2;
 258 
 259     path1 = vfs_path_get_last_path_str (vpath1);
 260     path2 = vfs_path_get_last_path_str (vpath2);
 261     return symlink (path1, path2);
 262 }
 263 
 264 /* --------------------------------------------------------------------------------------------- */
 265 
 266 static ssize_t
 267 local_write (void *data, const char *buf, size_t nbyte)
     /* [previous][next][first][last][top][bottom][index][help]  */
 268 {
 269     int fd;
 270     int n;
 271 
 272     if (data == NULL)
 273         return (-1);
 274 
 275     fd = *(int *) data;
 276 
 277     while ((n = write (fd, buf, nbyte)) == -1)
 278     {
 279 #ifdef EAGAIN
 280         if (errno == EAGAIN)
 281             continue;
 282 #endif
 283 #ifdef EINTR
 284         if (errno == EINTR)
 285             continue;
 286 #endif
 287         break;
 288     }
 289 
 290     return n;
 291 }
 292 
 293 /* --------------------------------------------------------------------------------------------- */
 294 
 295 static int
 296 local_rename (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 297 {
 298     const char *path1, *path2;
 299 
 300     path1 = vfs_path_get_last_path_str (vpath1);
 301     path2 = vfs_path_get_last_path_str (vpath2);
 302     return rename (path1, path2);
 303 }
 304 
 305 /* --------------------------------------------------------------------------------------------- */
 306 
 307 static int
 308 local_chdir (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 309 {
 310     const char *path;
 311 
 312     path = vfs_path_get_last_path_str (vpath);
 313     return chdir (path);
 314 }
 315 
 316 /* --------------------------------------------------------------------------------------------- */
 317 
 318 static int
 319 local_mknod (const vfs_path_t *vpath, mode_t mode, dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help]  */
 320 {
 321     const char *path;
 322 
 323     path = vfs_path_get_last_path_str (vpath);
 324     return mknod (path, mode, dev);
 325 }
 326 
 327 /* --------------------------------------------------------------------------------------------- */
 328 
 329 static int
 330 local_link (const vfs_path_t *vpath1, const vfs_path_t *vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 331 {
 332     const char *path1, *path2;
 333 
 334     path1 = vfs_path_get_last_path_str (vpath1);
 335     path2 = vfs_path_get_last_path_str (vpath2);
 336     return link (path1, path2);
 337 }
 338 
 339 /* --------------------------------------------------------------------------------------------- */
 340 
 341 static int
 342 local_mkdir (const vfs_path_t *vpath, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 343 {
 344     const char *path;
 345 
 346     path = vfs_path_get_last_path_str (vpath);
 347     return mkdir (path, mode);
 348 }
 349 
 350 /* --------------------------------------------------------------------------------------------- */
 351 
 352 static int
 353 local_rmdir (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 354 {
 355     const char *path;
 356 
 357     path = vfs_path_get_last_path_str (vpath);
 358     return rmdir (path);
 359 }
 360 
 361 /* --------------------------------------------------------------------------------------------- */
 362 
 363 static vfs_path_t *
 364 local_getlocalcopy (const vfs_path_t *vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 365 {
 366     return vfs_path_clone (vpath);
 367 }
 368 
 369 /* --------------------------------------------------------------------------------------------- */
 370 
 371 static int
 372 local_ungetlocalcopy (const vfs_path_t *vpath, const vfs_path_t *local, gboolean has_changed)
     /* [previous][next][first][last][top][bottom][index][help]  */
 373 {
 374     (void) vpath;
 375     (void) local;
 376     (void) has_changed;
 377 
 378     return 0;
 379 }
 380 
 381 /* --------------------------------------------------------------------------------------------- */
 382 
 383 static int
 384 local_which (struct vfs_class *me, const char *path)
     /* [previous][next][first][last][top][bottom][index][help]  */
 385 {
 386     (void) me;
 387     (void) path;
 388 
 389     return 0;  // Every path which other systems do not like is expected to be ours
 390 }
 391 
 392 /* --------------------------------------------------------------------------------------------- */
 393 /*** public functions ****************************************************************************/
 394 /* --------------------------------------------------------------------------------------------- */
 395 
 396 ssize_t
 397 local_read (void *data, char *buffer, size_t count)
     /* [previous][next][first][last][top][bottom][index][help]  */
 398 {
 399     int n;
 400     int fd;
 401 
 402     if (data == NULL)
 403         return (-1);
 404 
 405     fd = *(int *) data;
 406 
 407     while ((n = read (fd, buffer, count)) == -1)
 408     {
 409 #ifdef EAGAIN
 410         if (errno == EAGAIN)
 411             continue;
 412 #endif
 413 #ifdef EINTR
 414         if (errno == EINTR)
 415             continue;
 416 #endif
 417         return (-1);
 418     }
 419 
 420     return n;
 421 }
 422 
 423 /* --------------------------------------------------------------------------------------------- */
 424 
 425 int
 426 local_close (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 427 {
 428     int fd;
 429 
 430     if (data == NULL)
 431         return (-1);
 432 
 433     fd = *(int *) data;
 434     g_free (data);
 435     return close (fd);
 436 }
 437 
 438 /* --------------------------------------------------------------------------------------------- */
 439 
 440 int
 441 local_errno (struct vfs_class *me)
     /* [previous][next][first][last][top][bottom][index][help]  */
 442 {
 443     (void) me;
 444     return errno;
 445 }
 446 
 447 /* --------------------------------------------------------------------------------------------- */
 448 
 449 int
 450 local_fstat (void *data, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 451 {
 452     int fd = *(int *) data;
 453 
 454     return fstat (fd, buf);
 455 }
 456 
 457 /* --------------------------------------------------------------------------------------------- */
 458 
 459 off_t
 460 local_lseek (void *data, off_t offset, int whence)
     /* [previous][next][first][last][top][bottom][index][help]  */
 461 {
 462     int fd = *(int *) data;
 463 
 464     return lseek (fd, offset, whence);
 465 }
 466 
 467 /* --------------------------------------------------------------------------------------------- */
 468 
 469 static gboolean
 470 local_nothingisopen (vfsid id)
     /* [previous][next][first][last][top][bottom][index][help]  */
 471 {
 472     (void) id;
 473 
 474     return TRUE;
 475 }
 476 
 477 /* --------------------------------------------------------------------------------------------- */
 478 
 479 void
 480 vfs_init_localfs (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 481 {
 482     // NULLize vfs_s_subclass members
 483     memset (&local_subclass, 0, sizeof (local_subclass));
 484 
 485     vfs_init_class (vfs_local_ops, "localfs", VFSF_LOCAL, NULL);
 486     vfs_local_ops->which = local_which;
 487     vfs_local_ops->open = local_open;
 488     vfs_local_ops->close = local_close;
 489     vfs_local_ops->read = local_read;
 490     vfs_local_ops->write = local_write;
 491     vfs_local_ops->opendir = local_opendir;
 492     vfs_local_ops->readdir = local_readdir;
 493     vfs_local_ops->closedir = local_closedir;
 494     vfs_local_ops->stat = local_stat;
 495     vfs_local_ops->lstat = local_lstat;
 496     vfs_local_ops->fstat = local_fstat;
 497     vfs_local_ops->chmod = local_chmod;
 498     vfs_local_ops->chown = local_chown;
 499 #ifdef ENABLE_EXT2FS_ATTR
 500     vfs_local_ops->fgetflags = local_fgetflags;
 501     vfs_local_ops->fsetflags = local_fsetflags;
 502 #endif
 503     vfs_local_ops->utime = local_utime;
 504     vfs_local_ops->readlink = local_readlink;
 505     vfs_local_ops->symlink = local_symlink;
 506     vfs_local_ops->link = local_link;
 507     vfs_local_ops->unlink = local_unlink;
 508     vfs_local_ops->rename = local_rename;
 509     vfs_local_ops->chdir = local_chdir;
 510     vfs_local_ops->ferrno = local_errno;
 511     vfs_local_ops->lseek = local_lseek;
 512     vfs_local_ops->mknod = local_mknod;
 513     vfs_local_ops->getlocalcopy = local_getlocalcopy;
 514     vfs_local_ops->ungetlocalcopy = local_ungetlocalcopy;
 515     vfs_local_ops->mkdir = local_mkdir;
 516     vfs_local_ops->rmdir = local_rmdir;
 517     vfs_local_ops->nothingisopen = local_nothingisopen;
 518     vfs_register_class (vfs_local_ops);
 519 }
 520 
 521 /* --------------------------------------------------------------------------------------------- */

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