Coverage Report

Created: 2026-03-15 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/e2fsprogs/lib/ext2fs/fileio.c
Line
Count
Source
1
/*
2
 * fileio.c --- Simple file I/O routines
3
 *
4
 * Copyright (C) 1997 Theodore Ts'o.
5
 *
6
 * %Begin-Header%
7
 * This file may be redistributed under the terms of the GNU Library
8
 * General Public License, version 2.
9
 * %End-Header%
10
 */
11
12
#include "config.h"
13
#include <stdio.h>
14
#include <string.h>
15
#if HAVE_UNISTD_H
16
#include <unistd.h>
17
#endif
18
19
#include "ext2_fs.h"
20
#include "ext2fs.h"
21
#include "ext2fsP.h"
22
23
struct ext2_file {
24
  errcode_t   magic;
25
  ext2_filsys     fs;
26
  ext2_ino_t    ino;
27
  struct ext2_inode inode;
28
  int       flags;
29
  __u64     pos;
30
  blk64_t     blockno;
31
  blk64_t     physblock;
32
  char      *buf;
33
};
34
35
struct block_entry {
36
  blk64_t   physblock;
37
  unsigned char   sha[EXT2FS_SHA512_LENGTH];
38
};
39
typedef struct block_entry *block_entry_t;
40
41
0
#define BMAP_BUFFER (file->buf + fs->blocksize)
42
43
errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
44
          struct ext2_inode *inode,
45
          int flags, ext2_file_t *ret)
46
0
{
47
0
  ext2_file_t   file;
48
0
  errcode_t retval;
49
50
  /*
51
   * Don't let caller create or open a file for writing if the
52
   * filesystem is read-only.
53
   */
54
0
  if ((flags & (EXT2_FILE_WRITE | EXT2_FILE_CREATE)) &&
55
0
      !(fs->flags & EXT2_FLAG_RW))
56
0
    return EXT2_ET_RO_FILSYS;
57
58
0
  retval = ext2fs_get_mem(sizeof(struct ext2_file), &file);
59
0
  if (retval)
60
0
    return retval;
61
62
0
  memset(file, 0, sizeof(struct ext2_file));
63
0
  file->magic = EXT2_ET_MAGIC_EXT2_FILE;
64
0
  file->fs = fs;
65
0
  file->ino = ino;
66
0
  file->flags = flags & EXT2_FILE_MASK;
67
68
0
  if (inode) {
69
0
    memcpy(&file->inode, inode, sizeof(struct ext2_inode));
70
0
  } else {
71
0
    retval = ext2fs_read_inode(fs, ino, &file->inode);
72
0
    if (retval)
73
0
      goto fail;
74
0
  }
75
76
0
  retval = ext2fs_get_array(3, fs->blocksize, &file->buf);
77
0
  if (retval)
78
0
    goto fail;
79
80
0
  *ret = file;
81
0
  return 0;
82
83
0
fail:
84
0
  if (file->buf)
85
0
    ext2fs_free_mem(&file->buf);
86
0
  ext2fs_free_mem(&file);
87
0
  return retval;
88
0
}
89
90
errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
91
         int flags, ext2_file_t *ret)
92
0
{
93
0
  return ext2fs_file_open2(fs, ino, NULL, flags, ret);
94
0
}
95
96
/*
97
 * This function returns the filesystem handle of a file from the structure
98
 */
99
ext2_filsys ext2fs_file_get_fs(ext2_file_t file)
100
0
{
101
0
  if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
102
0
    return 0;
103
0
  return file->fs;
104
0
}
105
106
/*
107
 * This function returns the pointer to the inode of a file from the structure
108
 */
109
struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file)
110
0
{
111
0
  if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
112
0
    return NULL;
113
0
  return &file->inode;
114
0
}
115
116
/* This function returns the inode number from the structure */
117
ext2_ino_t ext2fs_file_get_inode_num(ext2_file_t file)
118
0
{
119
0
  if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
120
0
    return 0;
121
0
  return file->ino;
122
0
}
123
124
/*
125
 * This function flushes the dirty block buffer out to disk if
126
 * necessary.
127
 */
128
errcode_t ext2fs_file_flush(ext2_file_t file)
129
0
{
130
0
  errcode_t retval;
131
0
  ext2_filsys fs;
132
0
  int   ret_flags;
133
0
  blk64_t   dontcare;
134
135
0
  EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
136
0
  fs = file->fs;
137
138
0
  if (!(file->flags & EXT2_FILE_BUF_VALID) ||
139
0
      !(file->flags & EXT2_FILE_BUF_DIRTY))
140
0
    return 0;
141
142
  /* Is this an uninit block? */
143
0
  if (file->physblock && file->inode.i_flags & EXT4_EXTENTS_FL) {
144
0
    retval = ext2fs_bmap2(fs, file->ino, &file->inode, BMAP_BUFFER,
145
0
              0, file->blockno, &ret_flags, &dontcare);
146
0
    if (retval)
147
0
      return retval;
148
0
    if (ret_flags & BMAP_RET_UNINIT) {
149
0
      retval = ext2fs_bmap2(fs, file->ino, &file->inode,
150
0
                BMAP_BUFFER, BMAP_SET,
151
0
                file->blockno, 0,
152
0
                &file->physblock);
153
0
      if (retval)
154
0
        return retval;
155
0
    }
156
0
  }
157
158
  /*
159
   * OK, the physical block hasn't been allocated yet.
160
   * Allocate it.
161
   */
162
0
  if (!file->physblock) {
163
0
    retval = ext2fs_bmap2(fs, file->ino, &file->inode,
164
0
             BMAP_BUFFER, file->ino ? BMAP_ALLOC : 0,
165
0
             file->blockno, 0, &file->physblock);
166
0
    if (retval)
167
0
      return retval;
168
0
  }
169
170
0
  retval = io_channel_write_blk64(fs->io, file->physblock, 1, file->buf);
171
0
  if (retval)
172
0
    return retval;
173
174
0
  file->flags &= ~EXT2_FILE_BUF_DIRTY;
175
176
0
  return retval;
177
0
}
178
179
/*
180
 * This function synchronizes the file's block buffer and the current
181
 * file position, possibly invalidating block buffer if necessary
182
 */
183
static errcode_t sync_buffer_position(ext2_file_t file)
184
0
{
185
0
  blk64_t b;
186
0
  errcode_t retval;
187
188
0
  b = file->pos / file->fs->blocksize;
189
0
  if (b != file->blockno) {
190
0
    retval = ext2fs_file_flush(file);
191
0
    if (retval)
192
0
      return retval;
193
0
    file->flags &= ~EXT2_FILE_BUF_VALID;
194
0
  }
195
0
  file->blockno = b;
196
0
  return 0;
197
0
}
198
199
/*
200
 * This function loads the file's block buffer with valid data from
201
 * the disk as necessary.
202
 *
203
 * If dontfill is true, then skip initializing the buffer since we're
204
 * going to be replacing its entire contents anyway.  If set, then the
205
 * function basically only sets file->physblock and EXT2_FILE_BUF_VALID
206
 */
207
#define DONTFILL 1
208
static errcode_t load_buffer(ext2_file_t file, int dontfill)
209
0
{
210
0
  ext2_filsys fs = file->fs;
211
0
  errcode_t retval;
212
0
  int   ret_flags;
213
214
0
  if (!(file->flags & EXT2_FILE_BUF_VALID)) {
215
0
    retval = ext2fs_bmap2(fs, file->ino, &file->inode,
216
0
             BMAP_BUFFER, 0, file->blockno, &ret_flags,
217
0
             &file->physblock);
218
0
    if (retval)
219
0
      return retval;
220
0
    if (!dontfill) {
221
0
      if (file->physblock &&
222
0
          !(ret_flags & BMAP_RET_UNINIT)) {
223
0
        retval = io_channel_read_blk64(fs->io,
224
0
                     file->physblock,
225
0
                     1, file->buf);
226
0
        if (retval)
227
0
          return retval;
228
0
      } else
229
0
        memset(file->buf, 0, fs->blocksize);
230
0
    }
231
0
    file->flags |= EXT2_FILE_BUF_VALID;
232
0
  }
233
0
  return 0;
234
0
}
235
236
237
errcode_t ext2fs_file_close(ext2_file_t file)
238
0
{
239
0
  errcode_t retval;
240
241
0
  EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
242
243
0
  retval = ext2fs_file_flush(file);
244
245
0
  if (file->buf)
246
0
    ext2fs_free_mem(&file->buf);
247
0
  ext2fs_free_mem(&file);
248
249
0
  return retval;
250
0
}
251
252
253
static errcode_t
254
ext2fs_file_read_inline_data(ext2_file_t file, void *buf,
255
           unsigned int wanted, unsigned int *got)
256
0
{
257
0
  ext2_filsys fs;
258
0
  errcode_t retval = 0;
259
0
  unsigned int count = 0;
260
0
  uint64_t isize = EXT2_I_SIZE(&file->inode);
261
0
  size_t size;
262
263
0
  if (file->pos >= isize)
264
0
    goto out;
265
266
0
  fs = file->fs;
267
0
  retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
268
0
          file->buf, &size);
269
0
  if (retval)
270
0
    return retval;
271
272
  /*
273
   * size is the number of bytes available for inline data storage, which
274
   * means it can exceed isize.
275
   */
276
0
  if (size > isize)
277
0
    size = isize;
278
279
0
  count = size - file->pos;
280
0
  if (count > wanted)
281
0
    count = wanted;
282
0
  memcpy(buf, file->buf + file->pos, count);
283
0
  file->pos += count;
284
0
  buf = (char *) buf + count;
285
286
  /* zero-fill the rest of the buffer */
287
0
  wanted -= count;
288
0
  if (wanted > 0) {
289
0
    memset(buf, 0, wanted);
290
0
    file->pos += wanted;
291
0
    count += wanted;
292
0
  }
293
294
0
out:
295
0
  if (got)
296
0
    *got = count;
297
0
  return retval;
298
0
}
299
300
301
errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
302
         unsigned int wanted, unsigned int *got)
303
0
{
304
0
  ext2_filsys fs;
305
0
  errcode_t retval = 0;
306
0
  unsigned int  start, c, count = 0;
307
0
  __u64   left;
308
0
  char    *ptr = (char *) buf;
309
310
0
  EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
311
0
  fs = file->fs;
312
313
  /* If an inode has inline data, things get complicated. */
314
0
  if (file->inode.i_flags & EXT4_INLINE_DATA_FL)
315
0
    return ext2fs_file_read_inline_data(file, buf, wanted, got);
316
317
0
  while ((file->pos < EXT2_I_SIZE(&file->inode)) && (wanted > 0)) {
318
0
    retval = sync_buffer_position(file);
319
0
    if (retval)
320
0
      goto fail;
321
0
    retval = load_buffer(file, 0);
322
0
    if (retval)
323
0
      goto fail;
324
325
0
    start = file->pos % fs->blocksize;
326
0
    c = fs->blocksize - start;
327
0
    if (c > wanted)
328
0
      c = wanted;
329
0
    left = EXT2_I_SIZE(&file->inode) - file->pos ;
330
0
    if (c > left)
331
0
      c = left;
332
333
0
    memcpy(ptr, file->buf+start, c);
334
0
    file->pos += c;
335
0
    ptr += c;
336
0
    count += c;
337
0
    wanted -= c;
338
0
  }
339
340
0
fail:
341
0
  if (got)
342
0
    *got = count;
343
0
  return retval;
344
0
}
345
346
347
static errcode_t
348
ext2fs_file_write_inline_data(ext2_file_t file, const void *buf,
349
            unsigned int nbytes, unsigned int *written)
350
0
{
351
0
  ext2_filsys fs;
352
0
  uint64_t old_isize = EXT2_I_SIZE(&file->inode);
353
0
  uint64_t new_isize = old_isize;
354
0
  errcode_t retval;
355
0
  size_t size;
356
357
0
  if (file->pos + nbytes > old_isize)
358
0
    new_isize = file->pos + nbytes;
359
360
0
  fs = file->fs;
361
0
  retval = ext2fs_inline_data_get(fs, file->ino, &file->inode,
362
0
          file->buf, &size);
363
0
  if (retval)
364
0
    return retval;
365
366
  /*
367
   * Only try to set new inline data if it won't go past the end of
368
   * @file->buf; if there's not enough space in the ondisk inode, we'll
369
   * jump out to the expand code.
370
   */
371
0
  if (new_isize < fs->blocksize) {
372
0
    if (file->pos > old_isize)
373
0
      memset(file->buf + old_isize, 0, file->pos - old_isize);
374
375
0
    memcpy(file->buf + file->pos, buf, nbytes);
376
377
0
    retval = ext2fs_inline_data_set(fs, file->ino, &file->inode,
378
0
            file->buf, new_isize);
379
0
    if (retval == EXT2_ET_INLINE_DATA_NO_SPACE)
380
0
      goto expand;
381
0
    if (retval)
382
0
      return retval;
383
384
0
    file->pos += nbytes;
385
386
    /* Update inode size */
387
0
    if (old_isize < new_isize) {
388
0
      errcode_t rc;
389
390
0
      rc = ext2fs_file_set_size2(file, file->pos);
391
0
      if (retval == 0)
392
0
        retval = rc;
393
0
    }
394
395
0
    if (written)
396
0
      *written = nbytes;
397
0
    return 0;
398
0
  }
399
400
0
expand:
401
0
  retval = ext2fs_inline_data_expand(fs, file->ino);
402
0
  if (retval)
403
0
    return retval;
404
  /*
405
   * reload inode and return no space error
406
   *
407
   * XXX: file->inode could be copied from the outside
408
   * in ext2fs_file_open2().  We have no way to modify
409
   * the outside inode.
410
   */
411
0
  retval = ext2fs_read_inode(fs, file->ino, &file->inode);
412
0
  if (retval)
413
0
    return retval;
414
0
  return EXT2_ET_INLINE_DATA_NO_SPACE;
415
0
}
416
417
418
errcode_t ext2fs_file_write(ext2_file_t file, const void *buf,
419
          unsigned int nbytes, unsigned int *written)
420
0
{
421
0
  ext2_filsys fs;
422
0
  errcode_t retval = 0;
423
0
  unsigned int  start, c, count = 0;
424
0
  const char  *ptr = (const char *) buf;
425
0
  block_entry_t new_block = NULL, old_block = NULL;
426
0
  int   bmap_flags = 0;
427
428
0
  EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
429
0
  fs = file->fs;
430
431
0
  if (!(file->flags & EXT2_FILE_WRITE))
432
0
    return EXT2_ET_FILE_RO;
433
434
  /* If an inode has inline data, things get complicated. */
435
0
  if (file->inode.i_flags & EXT4_INLINE_DATA_FL) {
436
0
    retval = ext2fs_file_write_inline_data(file, buf, nbytes,
437
0
                   written);
438
0
    if (retval != EXT2_ET_INLINE_DATA_NO_SPACE)
439
0
      return retval;
440
    /* fall through to read data from the block */
441
0
    retval = 0;
442
0
  }
443
444
0
  while (nbytes > 0) {
445
0
    retval = sync_buffer_position(file);
446
0
    if (retval)
447
0
      goto fail;
448
449
0
    start = file->pos % fs->blocksize;
450
0
    c = fs->blocksize - start;
451
0
    if (c > nbytes)
452
0
      c = nbytes;
453
454
    /*
455
     * We only need to do a read-modify-update cycle if
456
     * we're doing a partial write.
457
     */
458
0
    retval = load_buffer(file, (c == fs->blocksize));
459
0
    if (retval)
460
0
      goto fail;
461
462
0
    file->flags |= EXT2_FILE_BUF_DIRTY;
463
0
    memcpy(file->buf+start, ptr, c);
464
465
    /*
466
     * OK, the physical block hasn't been allocated yet.
467
     * Allocate it.
468
     */
469
0
    if (!file->physblock) {
470
0
      bmap_flags = (file->ino ? BMAP_ALLOC : 0);
471
0
      if (fs->flags & EXT2_FLAG_SHARE_DUP) {
472
0
        new_block = calloc(1, sizeof(*new_block));
473
0
        if (!new_block) {
474
0
          retval = EXT2_ET_NO_MEMORY;
475
0
          goto fail;
476
0
        }
477
0
        ext2fs_sha512((const unsigned char*)file->buf,
478
0
            fs->blocksize, new_block->sha);
479
0
        old_block = ext2fs_hashmap_lookup(
480
0
              fs->block_sha_map,
481
0
              new_block->sha,
482
0
              sizeof(new_block->sha));
483
0
      }
484
485
0
      if (old_block) {
486
0
        file->physblock = old_block->physblock;
487
0
        bmap_flags |= BMAP_SET;
488
0
        free(new_block);
489
0
        new_block = NULL;
490
0
      }
491
492
0
      retval = ext2fs_bmap2(fs, file->ino, &file->inode,
493
0
                BMAP_BUFFER,
494
0
                bmap_flags,
495
0
                file->blockno, 0,
496
0
                &file->physblock);
497
0
      if (retval) {
498
0
        free(new_block);
499
0
        new_block = NULL;
500
0
        goto fail;
501
0
      }
502
503
0
      if (new_block) {
504
0
        new_block->physblock = file->physblock;
505
0
        int ret = ext2fs_hashmap_add(fs->block_sha_map,
506
0
            new_block, new_block->sha,
507
0
            sizeof(new_block->sha));
508
0
        if (ret) {
509
0
          retval = EXT2_ET_NO_MEMORY;
510
0
          free(new_block);
511
0
          goto fail;
512
0
        }
513
0
      }
514
515
0
      if (bmap_flags & BMAP_SET) {
516
0
        ext2fs_iblk_add_blocks(fs, &file->inode, 1);
517
0
        ext2fs_write_inode(fs, file->ino, &file->inode);
518
0
      }
519
0
    }
520
521
0
    file->pos += c;
522
0
    ptr += c;
523
0
    count += c;
524
0
    nbytes -= c;
525
0
  }
526
527
0
fail:
528
  /* Update inode size */
529
0
  if (count != 0 && EXT2_I_SIZE(&file->inode) < file->pos) {
530
0
    errcode_t rc;
531
532
0
    rc = ext2fs_file_set_size2(file, file->pos);
533
0
    if (retval == 0)
534
0
      retval = rc;
535
0
  }
536
537
0
  if (written)
538
0
    *written = count;
539
0
  return retval;
540
0
}
541
542
errcode_t ext2fs_file_llseek(ext2_file_t file, __u64 offset,
543
          int whence, __u64 *ret_pos)
544
0
{
545
0
  EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
546
547
0
  if (whence == EXT2_SEEK_SET)
548
0
    file->pos = offset;
549
0
  else if (whence == EXT2_SEEK_CUR)
550
0
    file->pos += offset;
551
0
  else if (whence == EXT2_SEEK_END)
552
0
    file->pos = EXT2_I_SIZE(&file->inode) + offset;
553
0
  else
554
0
    return EXT2_ET_INVALID_ARGUMENT;
555
556
0
  if (ret_pos)
557
0
    *ret_pos = file->pos;
558
559
0
  return 0;
560
0
}
561
562
errcode_t ext2fs_file_lseek(ext2_file_t file, ext2_off_t offset,
563
          int whence, ext2_off_t *ret_pos)
564
0
{
565
0
  __u64   loffset, ret_loffset = 0;
566
0
  errcode_t retval;
567
568
0
  loffset = offset;
569
0
  retval = ext2fs_file_llseek(file, loffset, whence, &ret_loffset);
570
0
  if (ret_pos)
571
0
    *ret_pos = (ext2_off_t) ret_loffset;
572
0
  return retval;
573
0
}
574
575
576
/*
577
 * This function returns the size of the file, according to the inode
578
 */
579
errcode_t ext2fs_file_get_lsize(ext2_file_t file, __u64 *ret_size)
580
0
{
581
0
  if (file->magic != EXT2_ET_MAGIC_EXT2_FILE)
582
0
    return EXT2_ET_MAGIC_EXT2_FILE;
583
0
  *ret_size = EXT2_I_SIZE(&file->inode);
584
0
  return 0;
585
0
}
586
587
/*
588
 * This function returns the size of the file, according to the inode
589
 */
590
ext2_off_t ext2fs_file_get_size(ext2_file_t file)
591
0
{
592
0
  __u64 size;
593
594
0
  if (ext2fs_file_get_lsize(file, &size))
595
0
    return 0;
596
0
  if ((size >> 32) != 0)
597
0
    return 0;
598
0
  return size;
599
0
}
600
601
/* Zero the parts of the last block that are past EOF. */
602
static errcode_t ext2fs_file_zero_past_offset(ext2_file_t file,
603
                ext2_off64_t offset)
604
0
{
605
0
  ext2_filsys fs = file->fs;
606
0
  char *b = NULL;
607
0
  ext2_off64_t off = offset % fs->blocksize;
608
0
  blk64_t blk;
609
0
  int ret_flags;
610
0
  errcode_t retval;
611
612
0
  if (off == 0)
613
0
    return 0;
614
615
0
  retval = sync_buffer_position(file);
616
0
  if (retval)
617
0
    return retval;
618
619
  /* Is there an initialized block at the end? */
620
0
  retval = ext2fs_bmap2(fs, file->ino, NULL, NULL, 0,
621
0
            offset / fs->blocksize, &ret_flags, &blk);
622
0
  if (retval)
623
0
    return retval;
624
0
  if ((blk == 0) || (ret_flags & BMAP_RET_UNINIT))
625
0
    return 0;
626
627
  /* Zero to the end of the block */
628
0
  retval = ext2fs_get_mem(fs->blocksize, &b);
629
0
  if (retval)
630
0
    return retval;
631
632
  /* Read/zero/write block */
633
0
  retval = io_channel_read_blk64(fs->io, blk, 1, b);
634
0
  if (retval)
635
0
    goto out;
636
637
0
  memset(b + off, 0, fs->blocksize - off);
638
639
0
  retval = io_channel_write_blk64(fs->io, blk, 1, b);
640
0
  if (retval)
641
0
    goto out;
642
643
0
out:
644
0
  ext2fs_free_mem(&b);
645
0
  return retval;
646
0
}
647
648
/*
649
 * This function sets the size of the file, truncating it if necessary
650
 *
651
 */
652
errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size)
653
0
{
654
0
  ext2_off64_t  old_size;
655
0
  errcode_t retval;
656
0
  blk64_t   old_truncate, truncate_block;
657
658
0
  EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
659
660
0
  if (size && ext2fs_file_block_offset_too_big(file->fs, &file->inode,
661
0
          (size - 1) / file->fs->blocksize))
662
0
    return EXT2_ET_FILE_TOO_BIG;
663
0
  truncate_block = ((size + file->fs->blocksize - 1) >>
664
0
        EXT2_BLOCK_SIZE_BITS(file->fs->super));
665
0
  old_size = EXT2_I_SIZE(&file->inode);
666
0
  old_truncate = ((old_size + file->fs->blocksize - 1) >>
667
0
          EXT2_BLOCK_SIZE_BITS(file->fs->super));
668
669
0
  retval = ext2fs_inode_size_set(file->fs, &file->inode, size);
670
0
  if (retval)
671
0
    return retval;
672
673
0
  if (file->ino) {
674
0
    retval = ext2fs_write_inode(file->fs, file->ino, &file->inode);
675
0
    if (retval)
676
0
      return retval;
677
0
  }
678
679
0
  retval = ext2fs_file_zero_past_offset(file, size);
680
0
  if (retval)
681
0
    return retval;
682
683
0
  if (truncate_block >= old_truncate)
684
0
    return 0;
685
686
0
  return ext2fs_punch(file->fs, file->ino, &file->inode, 0,
687
0
          truncate_block, ~0ULL);
688
0
}
689
690
errcode_t ext2fs_file_set_size(ext2_file_t file, ext2_off_t size)
691
0
{
692
0
  return ext2fs_file_set_size2(file, size);
693
0
}