Prex Home / Browse Source - Prex Version: 0.9.0

root/usr/server/fs/fatfs/fatfs_vnops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fat_read_cluster
  2. fat_write_cluster
  3. fatfs_lookup
  4. fatfs_read
  5. fatfs_write
  6. fatfs_readdir
  7. fatfs_create
  8. fatfs_remove
  9. fatfs_rename
  10. fatfs_mkdir
  11. fatfs_rmdir
  12. fatfs_getattr
  13. fatfs_setattr
  14. fatfs_inactive
  15. fatfs_truncate
  16. fatfs_init

   1 /*
   2  * Copyright (c) 2005-2008, Kohsuke Ohtani
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  * 3. Neither the name of the author nor the names of any co-contributors
  14  *    may be used to endorse or promote products derived from this software
  15  *    without specific prior written permission.
  16  *
  17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27  * SUCH DAMAGE.
  28  */
  29 
  30 #include <sys/prex.h>
  31 
  32 #include <sys/vnode.h>
  33 #include <sys/file.h>
  34 #include <sys/mount.h>
  35 #include <sys/dirent.h>
  36 #include <sys/buf.h>
  37 
  38 #include <ctype.h>
  39 #include <unistd.h>
  40 #include <errno.h>
  41 #include <string.h>
  42 #include <stdlib.h>
  43 #include <fcntl.h>
  44 
  45 #include "fatfs.h"
  46 
  47 /*
  48  *  Time bits: 15-11 hours (0-23), 10-5 min, 4-0 sec /2
  49  *  Date bits: 15-9 year - 1980, 8-5 month, 4-0 day
  50  */
  51 #define TEMP_DATE   0x3021
  52 #define TEMP_TIME   0
  53 
  54 #define fatfs_open      ((vnop_open_t)vop_nullop)
  55 #define fatfs_close     ((vnop_close_t)vop_nullop)
  56 static int fatfs_read   (vnode_t, file_t, void *, size_t, size_t *);
  57 static int fatfs_write  (vnode_t, file_t, void *, size_t, size_t *);
  58 #define fatfs_seek      ((vnop_seek_t)vop_nullop)
  59 #define fatfs_ioctl     ((vnop_ioctl_t)vop_einval)
  60 #define fatfs_fsync     ((vnop_fsync_t)vop_nullop)
  61 static int fatfs_readdir(vnode_t, file_t, struct dirent *);
  62 static int fatfs_lookup (vnode_t, char *, vnode_t);
  63 static int fatfs_create (vnode_t, char *, mode_t);
  64 static int fatfs_remove (vnode_t, vnode_t, char *);
  65 static int fatfs_rename (vnode_t, vnode_t, char *, vnode_t, vnode_t, char *);
  66 static int fatfs_mkdir  (vnode_t, char *, mode_t);
  67 static int fatfs_rmdir  (vnode_t, vnode_t, char *);
  68 static int fatfs_getattr(vnode_t, struct vattr *);
  69 static int fatfs_setattr(vnode_t, struct vattr *);
  70 static int fatfs_inactive(vnode_t);
  71 static int fatfs_truncate(vnode_t, off_t);
  72 
  73 /*
  74  * vnode operations
  75  */
  76 struct vnops fatfs_vnops = {
  77         fatfs_open,             /* open */
  78         fatfs_close,            /* close */
  79         fatfs_read,             /* read */
  80         fatfs_write,            /* write */
  81         fatfs_seek,             /* seek */
  82         fatfs_ioctl,            /* ioctl */
  83         fatfs_fsync,            /* fsync */
  84         fatfs_readdir,          /* readdir */
  85         fatfs_lookup,           /* lookup */
  86         fatfs_create,           /* create */
  87         fatfs_remove,           /* remove */
  88         fatfs_rename,           /* remame */
  89         fatfs_mkdir,            /* mkdir */
  90         fatfs_rmdir,            /* rmdir */
  91         fatfs_getattr,          /* getattr */
  92         fatfs_setattr,          /* setattr */
  93         fatfs_inactive,         /* inactive */
  94         fatfs_truncate,         /* truncate */
  95 };
  96 
  97 /*
  98  * Read one cluster to buffer.
  99  */
 100 static int
 101 fat_read_cluster(struct fatfsmount *fmp, u_long cluster)
 102 {
 103         u_long sec;
 104         size_t size;
 105 
 106         sec = cl_to_sec(fmp, cluster);
 107         size = fmp->sec_per_cl * SEC_SIZE;
 108         return device_read(fmp->dev, fmp->io_buf, &size, sec);
 109 }
 110 
 111 /*
 112  * Write one cluster from buffer.
 113  */
 114 static int
 115 fat_write_cluster(struct fatfsmount *fmp, u_long cluster)
 116 {
 117         u_long sec;
 118         size_t size;
 119 
 120         sec = cl_to_sec(fmp, cluster);
 121         size = fmp->sec_per_cl * SEC_SIZE;
 122         return device_write(fmp->dev, fmp->io_buf, &size, sec);
 123 }
 124 
 125 /*
 126  * Lookup vnode for the specified file/directory.
 127  * The vnode data will be set properly.
 128  */
 129 static int
 130 fatfs_lookup(vnode_t dvp, char *name, vnode_t vp)
 131 {
 132         struct fatfsmount *fmp;
 133         struct fat_dirent *de;
 134         struct fatfs_node *np;
 135         int error;
 136 
 137         if (*name == '\0')
 138                 return ENOENT;
 139 
 140         fmp = vp->v_mount->m_data;
 141         mutex_lock(&fmp->lock);
 142 
 143         DPRINTF(("fatfs_lookup: name=%s\n", name));
 144 
 145         np = vp->v_data;
 146         error = fatfs_lookup_node(dvp, name, np);
 147         if (error) {
 148                 DPRINTF(("fatfs_lookup: failed!! name=%s\n", name));
 149                 mutex_unlock(&fmp->lock);
 150                 return error;
 151         }
 152         de = &np->dirent;
 153         vp->v_type = IS_DIR(de) ? VDIR : VREG;
 154         fat_attr_to_mode(de->attr, &vp->v_mode);
 155         vp->v_mode = ALLPERMS;
 156         vp->v_size = de->size;
 157         vp->v_blkno = de->cluster;
 158 
 159         DPRINTF(("fatfs_lookup: cl=%d\n", de->cluster));
 160         mutex_unlock(&fmp->lock);
 161         return 0;
 162 }
 163 
 164 static int
 165 fatfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
 166 {
 167         struct fatfsmount *fmp;
 168         int nr_read, nr_copy, buf_pos, error;
 169         u_long cl, file_pos;
 170 
 171         DPRINTF(("fatfs_read: vp=%x\n", vp));
 172 
 173         *result = 0;
 174         fmp = vp->v_mount->m_data;
 175 
 176         if (vp->v_type == VDIR)
 177                 return EISDIR;
 178         if (vp->v_type != VREG)
 179                 return EINVAL;
 180 
 181         /* Check if current file position is already end of file. */
 182         file_pos = fp->f_offset;
 183         if (file_pos >= vp->v_size)
 184                 return 0;
 185 
 186         mutex_lock(&fmp->lock);
 187 
 188         /* Get the actual read size. */
 189         if (vp->v_size - file_pos < size)
 190                 size = vp->v_size - file_pos;
 191 
 192         /* Seek to the cluster for the file offset */
 193         error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl);
 194         if (error)
 195                 goto out;
 196 
 197         /* Read and copy data */
 198         nr_read = 0;
 199         buf_pos = file_pos % fmp->cluster_size;
 200         do {
 201                 if (fat_read_cluster(fmp, cl)) {
 202                         error = EIO;
 203                         goto out;
 204                 }
 205 
 206                 nr_copy = fmp->cluster_size;
 207                 if (buf_pos > 0)
 208                         nr_copy -= buf_pos;
 209                 if (buf_pos + size < fmp->cluster_size)
 210                         nr_copy = size;
 211                 memcpy(buf, fmp->io_buf + buf_pos, nr_copy);
 212 
 213                 file_pos += nr_copy;
 214                 nr_read += nr_copy;
 215                 size -= nr_copy;
 216                 if (size <= 0)
 217                         break;
 218 
 219                 error = fat_next_cluster(fmp, cl, &cl);
 220                 if (error)
 221                         goto out;
 222 
 223                 buf = (void *)((u_long)buf + nr_copy);
 224                 buf_pos = 0;
 225         } while (!IS_EOFCL(fmp, cl));
 226 
 227         fp->f_offset = file_pos;
 228         *result = nr_read;
 229         error = 0;
 230  out:
 231         mutex_unlock(&fmp->lock);
 232         return error;
 233 }
 234 
 235 static int
 236 fatfs_write(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
 237 {
 238         struct fatfsmount *fmp;
 239         struct fatfs_node *np;
 240         struct fat_dirent *de;
 241         int nr_copy, nr_write, buf_pos, i, cl_size, error;
 242         u_long file_pos, end_pos;
 243         u_long cl;
 244 
 245         DPRINTF(("fatfs_write: vp=%x\n", vp));
 246 
 247         *result = 0;
 248         fmp = vp->v_mount->m_data;
 249 
 250         if (vp->v_type == VDIR)
 251                 return EISDIR;
 252         if (vp->v_type != VREG)
 253                 return EINVAL;
 254 
 255         mutex_lock(&fmp->lock);
 256 
 257         /* Check if file position exceeds the end of file. */
 258         end_pos = vp->v_size;
 259         file_pos = (fp->f_flags & O_APPEND) ? end_pos : fp->f_offset;
 260         if (file_pos + size > end_pos) {
 261                 /* Expand the file size before writing to it */
 262                 end_pos = file_pos + size;
 263                 error = fat_expand_file(fmp, vp->v_blkno, end_pos);
 264                 if (error) {
 265                         error = EIO;
 266                         goto out;
 267                 }
 268 
 269                 /* Update directory entry */
 270                 np = vp->v_data;
 271                 de = &np->dirent;
 272                 de->size = end_pos;
 273                 error = fatfs_put_node(fmp, np);
 274                 if (error)
 275                         goto out;
 276                 vp->v_size = end_pos;
 277         }
 278 
 279         /* Seek to the cluster for the file offset */
 280         error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl);
 281         if (error)
 282                 goto out;
 283 
 284         buf_pos = file_pos % fmp->cluster_size;
 285         cl_size = size / fmp->cluster_size + 1;
 286         nr_write = 0;
 287         i = 0;
 288         do {
 289                 /* First and last cluster must be read before write */
 290                 if (i == 0 || i == cl_size) {
 291                         if (fat_read_cluster(fmp, cl)) {
 292                                 error = EIO;
 293                                 goto out;
 294                         }
 295                 }
 296                 nr_copy = fmp->cluster_size;
 297                 if (buf_pos > 0)
 298                         nr_copy -= buf_pos;
 299                 if (buf_pos + size < fmp->cluster_size)
 300                         nr_copy = size;
 301                 memcpy(fmp->io_buf + buf_pos, buf, nr_copy);
 302 
 303                 if (fat_write_cluster(fmp, cl)) {
 304                         error = EIO;
 305                         goto out;
 306                 }
 307                 file_pos += nr_copy;
 308                 nr_write += nr_copy;
 309                 size -= nr_copy;
 310                 if (size <= 0)
 311                         break;
 312 
 313                 error = fat_next_cluster(fmp, cl, &cl);
 314                 if (error)
 315                         goto out;
 316 
 317                 buf = (void *)((u_long)buf + nr_copy);
 318                 buf_pos = 0;
 319                 i++;
 320         } while (!IS_EOFCL(fmp, cl));
 321 
 322         fp->f_offset = file_pos;
 323 
 324         /*
 325          * XXX: Todo!
 326          *    de.time = ?
 327          *    de.date = ?
 328          *    if (dirent_set(fp, &de))
 329          *        return EIO;
 330          */
 331         *result = nr_write;
 332         error = 0;
 333  out:
 334         mutex_unlock(&fmp->lock);
 335         return error;
 336 }
 337 
 338 static int
 339 fatfs_readdir(vnode_t vp, file_t fp, struct dirent *dir)
 340 {
 341         struct fatfsmount *fmp;
 342         struct fatfs_node np;
 343         struct fat_dirent *de;
 344         int error;
 345 
 346         fmp = vp->v_mount->m_data;
 347         mutex_lock(&fmp->lock);
 348 
 349         error = fatfs_get_node(vp, fp->f_offset, &np);
 350         if (error)
 351                 goto out;
 352         de = &np.dirent;
 353         fat_restore_name((char *)&de->name, dir->d_name);
 354 
 355         if (de->attr & FA_SUBDIR)
 356                 dir->d_type = DT_DIR;
 357         else if (de->attr & FA_DEVICE)
 358                 dir->d_type = DT_BLK;
 359         else
 360                 dir->d_type = DT_REG;
 361 
 362         dir->d_fileno = fp->f_offset;
 363         dir->d_namlen = strlen(dir->d_name);
 364 
 365         fp->f_offset++;
 366         error = 0;
 367  out:
 368         mutex_unlock(&fmp->lock);
 369         return error;
 370 }
 371 
 372 /*
 373  * Create empty file.
 374  */
 375 static int
 376 fatfs_create(vnode_t dvp, char *name, mode_t mode)
 377 {
 378         struct fatfsmount *fmp;
 379         struct fatfs_node np;
 380         struct fat_dirent *de;
 381         u_long cl;
 382         int error;
 383 
 384         DPRINTF(("fatfs_create: %s\n", name));
 385 
 386         if (!S_ISREG(mode))
 387                 return EINVAL;
 388 
 389         if (!fat_valid_name(name))
 390                 return EINVAL;
 391 
 392         fmp = dvp->v_mount->m_data;
 393         mutex_lock(&fmp->lock);
 394 
 395         /* Allocate free cluster for new file. */
 396         error = fat_alloc_cluster(fmp, 0, &cl);
 397         if (error)
 398                 goto out;
 399 
 400         de = &np.dirent;
 401         memset(de, 0, sizeof(struct fat_dirent));
 402         fat_convert_name(name, (char *)de->name);
 403         de->cluster = cl;
 404         de->time = TEMP_TIME;
 405         de->date = TEMP_DATE;
 406         fat_mode_to_attr(mode, &de->attr);
 407         error = fatfs_add_node(dvp, &np);
 408         if (error)
 409                 goto out;
 410         error = fat_set_cluster(fmp, cl, fmp->fat_eof);
 411  out:
 412         mutex_unlock(&fmp->lock);
 413         return error;
 414 }
 415 
 416 static int
 417 fatfs_remove(vnode_t dvp, vnode_t vp, char *name)
 418 {
 419         struct fatfsmount *fmp;
 420         struct fatfs_node np;
 421         struct fat_dirent *de;
 422         int error;
 423 
 424         if (*name == '\0')
 425                 return ENOENT;
 426 
 427         fmp = dvp->v_mount->m_data;
 428         mutex_lock(&fmp->lock);
 429 
 430         error = fatfs_lookup_node(dvp, name, &np);
 431         if (error)
 432                 goto out;
 433         de = &np.dirent;
 434         if (IS_DIR(de)) {
 435                 error = EISDIR;
 436                 goto out;
 437         }
 438         if (!IS_FILE(de)) {
 439                 error = EPERM;
 440                 goto out;
 441         }
 442 
 443         /* Remove clusters */
 444         error = fat_free_clusters(fmp, de->cluster);
 445         if (error)
 446                 goto out;
 447 
 448         /* remove directory */
 449         de->name[0] = 0xe5;
 450         error = fatfs_put_node(fmp, &np);
 451  out:
 452         mutex_unlock(&fmp->lock);
 453         return error;
 454 }
 455 
 456 static int
 457 fatfs_rename(vnode_t dvp1, vnode_t vp1, char *name1,
 458              vnode_t dvp2, vnode_t vp2, char *name2)
 459 {
 460         struct fatfsmount *fmp;
 461         struct fatfs_node np1;
 462         struct fat_dirent *de1, *de2;
 463         int error;
 464 
 465         fmp = dvp1->v_mount->m_data;
 466         mutex_lock(&fmp->lock);
 467 
 468         error = fatfs_lookup_node(dvp1, name1, &np1);
 469         if (error)
 470                 goto out;
 471         de1 = &np1.dirent;
 472 
 473         if (IS_FILE(de1)) {
 474                 /* Remove destination file, first */
 475                 error = fatfs_remove(dvp2, vp1, name2);
 476                 if (error == EIO)
 477                         goto out;
 478 
 479                 /* Change file name of directory entry */
 480                 fat_convert_name(name2, (char *)de1->name);
 481 
 482                 /* Same directory ? */
 483                 if (dvp1 == dvp2) {
 484                         /* Change the name of existing file */
 485                         error = fatfs_put_node(fmp, &np1);
 486                         if (error)
 487                                 goto out;
 488                 } else {
 489                         /* Create new directory entry */
 490                         error = fatfs_add_node(dvp2, &np1);
 491                         if (error)
 492                                 goto out;
 493 
 494                         /* Remove souce file */
 495                         error = fatfs_remove(dvp1, vp2, name1);
 496                         if (error)
 497                                 goto out;
 498                 }
 499         } else {
 500 
 501                 /* remove destination directory */
 502                 error = fatfs_rmdir(dvp2, NULL, name2);
 503                 if (error == EIO)
 504                         goto out;
 505 
 506                 /* Change file name of directory entry */
 507                 fat_convert_name(name2, (char *)de1->name);
 508 
 509                 /* Same directory ? */
 510                 if (dvp1 == dvp2) {
 511                         /* Change the name of existing directory */
 512                         error = fatfs_put_node(fmp, &np1);
 513                         if (error)
 514                                 goto out;
 515                 } else {
 516                         /* Create new directory entry */
 517                         error = fatfs_add_node(dvp2, &np1);
 518                         if (error)
 519                                 goto out;
 520 
 521                         /* Update "." and ".." for renamed directory */
 522                         if (fat_read_cluster(fmp, de1->cluster)) {
 523                                 error = EIO;
 524                                 goto out;
 525                         }
 526 
 527                         de2 = (struct fat_dirent *)fmp->io_buf;
 528                         de2->cluster = de1->cluster;
 529                         de2->time = TEMP_TIME;
 530                         de2->date = TEMP_DATE;
 531                         de2++;
 532                         de2->cluster = dvp2->v_blkno;
 533                         de2->time = TEMP_TIME;
 534                         de2->date = TEMP_DATE;
 535 
 536                         if (fat_write_cluster(fmp, de1->cluster)) {
 537                                 error = EIO;
 538                                 goto out;
 539                         }
 540 
 541                         /* Remove souce directory */
 542                         error = fatfs_rmdir(dvp1, NULL, name1);
 543                         if (error)
 544                                 goto out;
 545                 }
 546         }
 547  out:
 548         mutex_unlock(&fmp->lock);
 549         return error;
 550 }
 551 
 552 static int
 553 fatfs_mkdir(vnode_t dvp, char *name, mode_t mode)
 554 {
 555         struct fatfsmount *fmp;
 556         struct fatfs_node np;
 557         struct fat_dirent *de;
 558         u_long cl;
 559         int error;
 560 
 561         if (!S_ISDIR(mode))
 562                 return EINVAL;
 563 
 564         if (!fat_valid_name(name))
 565                 return ENOTDIR;
 566 
 567         fmp = dvp->v_mount->m_data;
 568         mutex_lock(&fmp->lock);
 569 
 570         /* Allocate free cluster for directory data */
 571         error = fat_alloc_cluster(fmp, 0, &cl);
 572         if (error)
 573                 goto out;
 574 
 575         memset(&np, 0, sizeof(struct fatfs_node));
 576         de = &np.dirent;
 577         fat_convert_name(name, (char *)&de->name);
 578         de->cluster = cl;
 579         de->time = TEMP_TIME;
 580         de->date = TEMP_DATE;
 581         fat_mode_to_attr(mode, &de->attr);
 582         error = fatfs_add_node(dvp, &np);
 583         if (error)
 584                 goto out;
 585 
 586         /* Initialize "." and ".." for new directory */
 587         memset(fmp->io_buf, 0, fmp->cluster_size);
 588 
 589         de = (struct fat_dirent *)fmp->io_buf;
 590         memcpy(de->name, ".          ", 11);
 591         de->attr = FA_SUBDIR;
 592         de->cluster = cl;
 593         de->time = TEMP_TIME;
 594         de->date = TEMP_DATE;
 595         de++;
 596         memcpy(de->name, "..         ", 11);
 597         de->attr = FA_SUBDIR;
 598         de->cluster = dvp->v_blkno;
 599         de->time = TEMP_TIME;
 600         de->date = TEMP_DATE;
 601 
 602         if (fat_write_cluster(fmp, cl)) {
 603                 error = EIO;
 604                 goto out;
 605         }
 606         /* Add eof */
 607         error = fat_set_cluster(fmp, cl, fmp->fat_eof);
 608  out:
 609         mutex_unlock(&fmp->lock);
 610         return error;
 611 }
 612 
 613 /*
 614  * remove can be done only with empty directory
 615  */
 616 static int
 617 fatfs_rmdir(vnode_t dvp, vnode_t vp, char *name)
 618 {
 619         struct fatfsmount *fmp;
 620         struct fatfs_node np;
 621         struct fat_dirent *de;
 622         int error;
 623 
 624         if (*name == '\0')
 625                 return ENOENT;
 626 
 627         fmp = dvp->v_mount->m_data;
 628         mutex_lock(&fmp->lock);
 629 
 630         error = fatfs_lookup_node(dvp, name, &np);
 631         if (error)
 632                 goto out;
 633 
 634         de = &np.dirent;
 635         if (!IS_DIR(de)) {
 636                 error = ENOTDIR;
 637                 goto out;
 638         }
 639 
 640         /* Remove clusters */
 641         error = fat_free_clusters(fmp, de->cluster);
 642         if (error)
 643                 goto out;
 644 
 645         /* remove directory */
 646         de->name[0] = 0xe5;
 647 
 648         error = fatfs_put_node(fmp, &np);
 649  out:
 650         mutex_unlock(&fmp->lock);
 651         return error;
 652 }
 653 
 654 static int
 655 fatfs_getattr(vnode_t vp, struct vattr *vap)
 656 {
 657         /* XXX */
 658         return 0;
 659 }
 660 
 661 static int
 662 fatfs_setattr(vnode_t vp, struct vattr *vap)
 663 {
 664         /* XXX */
 665         return 0;
 666 }
 667 
 668 
 669 static int
 670 fatfs_inactive(vnode_t vp)
 671 {
 672 
 673         free(vp->v_data);
 674         return 0;
 675 }
 676 
 677 static int
 678 fatfs_truncate(vnode_t vp, off_t length)
 679 {
 680         struct fatfsmount *fmp;
 681         struct fatfs_node *np;
 682         struct fat_dirent *de;
 683         int error;
 684 
 685         fmp = vp->v_mount->m_data;
 686         mutex_lock(&fmp->lock);
 687 
 688         np = vp->v_data;
 689         de = &np->dirent;
 690 
 691         if (length == 0) {
 692                 /* Remove clusters */
 693                 error = fat_free_clusters(fmp, de->cluster);
 694                 if (error)
 695                         goto out;
 696         } else if (length > vp->v_size) {
 697                 error = fat_expand_file(fmp, vp->v_blkno, length);
 698                 if (error) {
 699                         error = EIO;
 700                         goto out;
 701                 }
 702         }
 703 
 704         /* Update directory entry */
 705         de->size = length;
 706         error = fatfs_put_node(fmp, np);
 707         if (error)
 708                 goto out;
 709         vp->v_size = length;
 710  out:
 711         mutex_unlock(&fmp->lock);
 712         return error;
 713 }
 714 
 715 int
 716 fatfs_init(void)
 717 {
 718         return 0;
 719 }

/* [<][>][^][v][top][bottom][index][help] */