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-2024
   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 <http://www.gnu.org/licenses/>.
  21  */
  22 
  23 /**
  24  * \file
  25  * \brief Source: local FS
  26  */
  27 
  28 #include <config.h>
  29 #include <errno.h>
  30 #include <sys/types.h>
  31 #include <unistd.h>
  32 #include <stdio.h>
  33 #include <string.h>
  34 #ifdef ENABLE_EXT2FS_ATTR
  35 #include <e2p/e2p.h>            /* fgetflags(), fsetflags() */
  36 #endif
  37 
  38 #include "lib/global.h"
  39 
  40 #include "lib/vfs/xdirentry.h"  /* vfs_s_subclass */
  41 #include "lib/vfs/utilvfs.h"
  42 
  43 #include "local.h"
  44 
  45 /*** global variables ****************************************************************************/
  46 
  47 /*** file scope macro definitions ****************************************************************/
  48 
  49 /*** file scope type declarations ****************************************************************/
  50 
  51 /*** forward declarations (file scope functions) *************************************************/
  52 
  53 /*** file scope variables ************************************************************************/
  54 
  55 static struct vfs_s_subclass local_subclass;
  56 static struct vfs_class *vfs_local_ops = VFS_CLASS (&local_subclass);
  57 
  58 /* --------------------------------------------------------------------------------------------- */
  59 /*** file scope functions ************************************************************************/
  60 /* --------------------------------------------------------------------------------------------- */
  61 
  62 static void *
  63 local_open (const vfs_path_t * vpath, int flags, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
  64 {
  65     int *local_info;
  66     int fd;
  67     const char *path;
  68 
  69     path = vfs_path_get_last_path_str (vpath);
  70     fd = open (path, NO_LINEAR (flags), mode);
  71     if (fd == -1)
  72         return 0;
  73 
  74     local_info = g_new (int, 1);
  75     *local_info = fd;
  76 
  77     return local_info;
  78 }
  79 
  80 /* --------------------------------------------------------------------------------------------- */
  81 
  82 static void *
  83 local_opendir (const vfs_path_t * vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
  84 {
  85     DIR **local_info;
  86     DIR *dir = NULL;
  87     const char *path;
  88 
  89     path = vfs_path_get_last_path_str (vpath);
  90 
  91     /* On Linux >= 5.1, MC sometimes shows empty directories on mounted CIFS shares.
  92      * Rereading directory restores the directory content.
  93      *
  94      * Reopen directory, if first readdir() returns NULL and errno == EINTR.
  95      */
  96     while (dir == NULL)
  97     {
  98         dir = opendir (path);
  99         if (dir == NULL)
 100             return NULL;
 101 
 102         if (readdir (dir) == NULL && errno == EINTR)
 103         {
 104             closedir (dir);
 105             dir = NULL;
 106         }
 107         else
 108             rewinddir (dir);
 109     }
 110 
 111     local_info = (DIR **) g_new (DIR *, 1);
 112     *local_info = dir;
 113 
 114     return local_info;
 115 }
 116 
 117 /* --------------------------------------------------------------------------------------------- */
 118 
 119 static struct vfs_dirent *
 120 local_readdir (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 121 {
 122     struct dirent *d;
 123 
 124     d = readdir (*(DIR **) data);
 125 
 126     return (d != NULL ? vfs_dirent_init (NULL, d->d_name, d->d_ino) : NULL);
 127 }
 128 
 129 /* --------------------------------------------------------------------------------------------- */
 130 
 131 static int
 132 local_closedir (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 133 {
 134     int i;
 135 
 136     i = closedir (*(DIR **) data);
 137     g_free (data);
 138     return i;
 139 }
 140 
 141 /* --------------------------------------------------------------------------------------------- */
 142 
 143 static int
 144 local_stat (const vfs_path_t * vpath, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 145 {
 146     const char *path;
 147 
 148     path = vfs_path_get_last_path_str (vpath);
 149     return stat (path, buf);
 150 }
 151 
 152 /* --------------------------------------------------------------------------------------------- */
 153 
 154 static int
 155 local_lstat (const vfs_path_t * vpath, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 156 {
 157     const char *path;
 158 
 159     path = vfs_path_get_last_path_str (vpath);
 160 #ifndef HAVE_STATLSTAT
 161     return lstat (path, buf);
 162 #else
 163     return statlstat (path, buf);
 164 #endif
 165 }
 166 
 167 /* --------------------------------------------------------------------------------------------- */
 168 
 169 static int
 170 local_chmod (const vfs_path_t * vpath, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 171 {
 172     const char *path;
 173 
 174     path = vfs_path_get_last_path_str (vpath);
 175     return chmod (path, mode);
 176 }
 177 
 178 /* --------------------------------------------------------------------------------------------- */
 179 
 180 static int
 181 local_chown (const vfs_path_t * vpath, uid_t owner, gid_t group)
     /* [previous][next][first][last][top][bottom][index][help]  */
 182 {
 183     const char *path;
 184 
 185     path = vfs_path_get_last_path_str (vpath);
 186     return chown (path, owner, group);
 187 }
 188 
 189 /* --------------------------------------------------------------------------------------------- */
 190 
 191 #ifdef ENABLE_EXT2FS_ATTR
 192 
 193 static int
 194 local_fgetflags (const vfs_path_t * vpath, unsigned long *flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 195 {
 196     const char *path;
 197 
 198     path = vfs_path_get_last_path_str (vpath);
 199     return fgetflags (path, flags);
 200 }
 201 
 202 /* --------------------------------------------------------------------------------------------- */
 203 
 204 static int
 205 local_fsetflags (const vfs_path_t * vpath, unsigned long flags)
     /* [previous][next][first][last][top][bottom][index][help]  */
 206 {
 207     const char *path;
 208 
 209     path = vfs_path_get_last_path_str (vpath);
 210     return fsetflags (path, flags);
 211 }
 212 
 213 #endif /* ENABLE_EXT2FS_ATTR */
 214 
 215 /* --------------------------------------------------------------------------------------------- */
 216 
 217 static int
 218 local_utime (const vfs_path_t * vpath, mc_timesbuf_t * times)
     /* [previous][next][first][last][top][bottom][index][help]  */
 219 {
 220     int ret;
 221     const char *path;
 222 
 223     path = vfs_path_get_last_path_str (vpath);
 224 #ifdef HAVE_UTIMENSAT
 225     ret = utimensat (AT_FDCWD, path, *times, AT_SYMLINK_NOFOLLOW);
 226 #else
 227     ret = utime (path, times);
 228 #endif
 229     return ret;
 230 }
 231 
 232 /* --------------------------------------------------------------------------------------------- */
 233 
 234 static int
 235 local_readlink (const vfs_path_t * vpath, char *buf, size_t size)
     /* [previous][next][first][last][top][bottom][index][help]  */
 236 {
 237     const char *path;
 238 
 239     path = vfs_path_get_last_path_str (vpath);
 240     return readlink (path, buf, size);
 241 }
 242 
 243 /* --------------------------------------------------------------------------------------------- */
 244 
 245 static int
 246 local_unlink (const vfs_path_t * vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 247 {
 248     const char *path;
 249 
 250     path = vfs_path_get_last_path_str (vpath);
 251     return unlink (path);
 252 }
 253 
 254 /* --------------------------------------------------------------------------------------------- */
 255 
 256 static int
 257 local_symlink (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 258 {
 259     const char *path1, *path2;
 260 
 261     path1 = vfs_path_get_last_path_str (vpath1);
 262     path2 = vfs_path_get_last_path_str (vpath2);
 263     return symlink (path1, path2);
 264 }
 265 
 266 /* --------------------------------------------------------------------------------------------- */
 267 
 268 static ssize_t
 269 local_write (void *data, const char *buf, size_t nbyte)
     /* [previous][next][first][last][top][bottom][index][help]  */
 270 {
 271     int fd;
 272     int n;
 273 
 274     if (data == NULL)
 275         return (-1);
 276 
 277     fd = *(int *) data;
 278 
 279     while ((n = write (fd, buf, nbyte)) == -1)
 280     {
 281 #ifdef EAGAIN
 282         if (errno == EAGAIN)
 283             continue;
 284 #endif
 285 #ifdef EINTR
 286         if (errno == EINTR)
 287             continue;
 288 #endif
 289         break;
 290     }
 291 
 292     return n;
 293 }
 294 
 295 /* --------------------------------------------------------------------------------------------- */
 296 
 297 static int
 298 local_rename (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 299 {
 300     const char *path1, *path2;
 301 
 302     path1 = vfs_path_get_last_path_str (vpath1);
 303     path2 = vfs_path_get_last_path_str (vpath2);
 304     return rename (path1, path2);
 305 }
 306 
 307 /* --------------------------------------------------------------------------------------------- */
 308 
 309 static int
 310 local_chdir (const vfs_path_t * vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 311 {
 312     const char *path;
 313 
 314     path = vfs_path_get_last_path_str (vpath);
 315     return chdir (path);
 316 }
 317 
 318 /* --------------------------------------------------------------------------------------------- */
 319 
 320 static int
 321 local_mknod (const vfs_path_t * vpath, mode_t mode, dev_t dev)
     /* [previous][next][first][last][top][bottom][index][help]  */
 322 {
 323     const char *path;
 324 
 325     path = vfs_path_get_last_path_str (vpath);
 326     return mknod (path, mode, dev);
 327 }
 328 
 329 /* --------------------------------------------------------------------------------------------- */
 330 
 331 static int
 332 local_link (const vfs_path_t * vpath1, const vfs_path_t * vpath2)
     /* [previous][next][first][last][top][bottom][index][help]  */
 333 {
 334     const char *path1, *path2;
 335 
 336     path1 = vfs_path_get_last_path_str (vpath1);
 337     path2 = vfs_path_get_last_path_str (vpath2);
 338     return link (path1, path2);
 339 }
 340 
 341 /* --------------------------------------------------------------------------------------------- */
 342 
 343 static int
 344 local_mkdir (const vfs_path_t * vpath, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help]  */
 345 {
 346     const char *path;
 347 
 348     path = vfs_path_get_last_path_str (vpath);
 349     return mkdir (path, mode);
 350 }
 351 
 352 /* --------------------------------------------------------------------------------------------- */
 353 
 354 static int
 355 local_rmdir (const vfs_path_t * vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 356 {
 357     const char *path;
 358 
 359     path = vfs_path_get_last_path_str (vpath);
 360     return rmdir (path);
 361 }
 362 
 363 /* --------------------------------------------------------------------------------------------- */
 364 
 365 static vfs_path_t *
 366 local_getlocalcopy (const vfs_path_t * vpath)
     /* [previous][next][first][last][top][bottom][index][help]  */
 367 {
 368     return vfs_path_clone (vpath);
 369 }
 370 
 371 /* --------------------------------------------------------------------------------------------- */
 372 
 373 static int
 374 local_ungetlocalcopy (const vfs_path_t * vpath, const vfs_path_t * local, gboolean has_changed)
     /* [previous][next][first][last][top][bottom][index][help]  */
 375 {
 376     (void) vpath;
 377     (void) local;
 378     (void) has_changed;
 379 
 380     return 0;
 381 }
 382 
 383 /* --------------------------------------------------------------------------------------------- */
 384 
 385 static int
 386 local_which (struct vfs_class *me, const char *path)
     /* [previous][next][first][last][top][bottom][index][help]  */
 387 {
 388     (void) me;
 389     (void) path;
 390 
 391     return 0;                   /* Every path which other systems do not like is expected to be ours */
 392 }
 393 
 394 /* --------------------------------------------------------------------------------------------- */
 395 /*** public functions ****************************************************************************/
 396 /* --------------------------------------------------------------------------------------------- */
 397 
 398 ssize_t
 399 local_read (void *data, char *buffer, size_t count)
     /* [previous][next][first][last][top][bottom][index][help]  */
 400 {
 401     int n;
 402     int fd;
 403 
 404     if (data == NULL)
 405         return (-1);
 406 
 407     fd = *(int *) data;
 408 
 409     while ((n = read (fd, buffer, count)) == -1)
 410     {
 411 #ifdef EAGAIN
 412         if (errno == EAGAIN)
 413             continue;
 414 #endif
 415 #ifdef EINTR
 416         if (errno == EINTR)
 417             continue;
 418 #endif
 419         return (-1);
 420     }
 421 
 422     return n;
 423 }
 424 
 425 /* --------------------------------------------------------------------------------------------- */
 426 
 427 int
 428 local_close (void *data)
     /* [previous][next][first][last][top][bottom][index][help]  */
 429 {
 430     int fd;
 431 
 432     if (data == NULL)
 433         return (-1);
 434 
 435     fd = *(int *) data;
 436     g_free (data);
 437     return close (fd);
 438 }
 439 
 440 /* --------------------------------------------------------------------------------------------- */
 441 
 442 int
 443 local_errno (struct vfs_class *me)
     /* [previous][next][first][last][top][bottom][index][help]  */
 444 {
 445     (void) me;
 446     return errno;
 447 }
 448 
 449 /* --------------------------------------------------------------------------------------------- */
 450 
 451 int
 452 local_fstat (void *data, struct stat *buf)
     /* [previous][next][first][last][top][bottom][index][help]  */
 453 {
 454     int fd = *(int *) data;
 455 
 456     return fstat (fd, buf);
 457 }
 458 
 459 /* --------------------------------------------------------------------------------------------- */
 460 
 461 off_t
 462 local_lseek (void *data, off_t offset, int whence)
     /* [previous][next][first][last][top][bottom][index][help]  */
 463 {
 464     int fd = *(int *) data;
 465 
 466     return lseek (fd, offset, whence);
 467 }
 468 
 469 /* --------------------------------------------------------------------------------------------- */
 470 
 471 static gboolean
 472 local_nothingisopen (vfsid id)
     /* [previous][next][first][last][top][bottom][index][help]  */
 473 {
 474     (void) id;
 475 
 476     return TRUE;
 477 }
 478 
 479 /* --------------------------------------------------------------------------------------------- */
 480 
 481 void
 482 vfs_init_localfs (void)
     /* [previous][next][first][last][top][bottom][index][help]  */
 483 {
 484     /* NULLize vfs_s_subclass members */
 485     memset (&local_subclass, 0, sizeof (local_subclass));
 486 
 487     vfs_init_class (vfs_local_ops, "localfs", VFSF_LOCAL, NULL);
 488     vfs_local_ops->which = local_which;
 489     vfs_local_ops->open = local_open;
 490     vfs_local_ops->close = local_close;
 491     vfs_local_ops->read = local_read;
 492     vfs_local_ops->write = local_write;
 493     vfs_local_ops->opendir = local_opendir;
 494     vfs_local_ops->readdir = local_readdir;
 495     vfs_local_ops->closedir = local_closedir;
 496     vfs_local_ops->stat = local_stat;
 497     vfs_local_ops->lstat = local_lstat;
 498     vfs_local_ops->fstat = local_fstat;
 499     vfs_local_ops->chmod = local_chmod;
 500     vfs_local_ops->chown = local_chown;
 501 #ifdef ENABLE_EXT2FS_ATTR
 502     vfs_local_ops->fgetflags = local_fgetflags;
 503     vfs_local_ops->fsetflags = local_fsetflags;
 504 #endif
 505     vfs_local_ops->utime = local_utime;
 506     vfs_local_ops->readlink = local_readlink;
 507     vfs_local_ops->symlink = local_symlink;
 508     vfs_local_ops->link = local_link;
 509     vfs_local_ops->unlink = local_unlink;
 510     vfs_local_ops->rename = local_rename;
 511     vfs_local_ops->chdir = local_chdir;
 512     vfs_local_ops->ferrno = local_errno;
 513     vfs_local_ops->lseek = local_lseek;
 514     vfs_local_ops->mknod = local_mknod;
 515     vfs_local_ops->getlocalcopy = local_getlocalcopy;
 516     vfs_local_ops->ungetlocalcopy = local_ungetlocalcopy;
 517     vfs_local_ops->mkdir = local_mkdir;
 518     vfs_local_ops->rmdir = local_rmdir;
 519     vfs_local_ops->nothingisopen = local_nothingisopen;
 520     vfs_register_class (vfs_local_ops);
 521 }
 522 
 523 /* --------------------------------------------------------------------------------------------- */

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