~ubuntu-branches/debian/sid/neovim/sid

« back to all changes in this revision

Viewing changes to src/nvim/memfile.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2016-04-18 21:42:19 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20160418214219-1e6d4o1fwqarzk46
Tags: 0.1.3-1
* New upstream release.  (Closes: #820562)
* debian/control:
  + Remove unnecessary luarocks Build-Depends
  + Add libkvm-dev Build-Depends for kfreebsd-*
  + Add python(3)-neovim to Recommends.  (Closes: #812737)
  + Declare compiance with policy 3.9.8, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
79
79
///         - NULL, on failure.
80
80
memfile_T *mf_open(char_u *fname, int flags)
81
81
{
82
 
  off_t size;
83
 
 
84
82
  memfile_T *mfp = xmalloc(sizeof(memfile_T));
85
83
 
86
84
  if (fname == NULL) {               // no file, use memory only
88
86
    mfp->mf_ffname = NULL;
89
87
    mfp->mf_fd = -1;
90
88
  } else {                           // try to open the file
91
 
    mf_do_open(mfp, fname, flags);
92
 
 
93
 
    if (mfp->mf_fd < 0) {            // fail if file could not be opened
 
89
    if (!mf_do_open(mfp, fname, flags)) {
94
90
      xfree(mfp);
95
 
      return NULL;
 
91
      return NULL;                   // fail if file could not be opened
96
92
    }
97
93
  }
98
94
 
115
111
    }
116
112
  }
117
113
 
 
114
  off_t size;
 
115
 
118
116
  // When recovering, the actual block size will be retrieved from block 0
119
117
  // in ml_recover(). The size used here may be wrong, therefore mf_blocknr_max
120
118
  // must be rounded up.
171
169
///         FAIL  If file could not be opened.
172
170
int mf_open_file(memfile_T *mfp, char_u *fname)
173
171
{
174
 
  mf_do_open(mfp, fname, O_RDWR|O_CREAT|O_EXCL);  // try to open the file
175
 
 
176
 
  if (mfp->mf_fd < 0)
177
 
    return FAIL;
178
 
 
179
 
  mfp->mf_dirty = true;
180
 
  return OK;
 
172
  if (mf_do_open(mfp, fname, O_RDWR | O_CREAT | O_EXCL)) {
 
173
    mfp->mf_dirty = true;
 
174
    return OK;
 
175
  }
 
176
 
 
177
  return FAIL;
181
178
}
182
179
 
183
180
/// Close a memory file and optionally delete the associated file.
185
182
/// @param del_file  Whether to delete associated file.
186
183
void mf_close(memfile_T *mfp, bool del_file)
187
184
{
188
 
  bhdr_T      *hp, *nextp;
189
 
 
190
185
  if (mfp == NULL) {                    // safety check
191
186
    return;
192
187
  }
193
188
  if (mfp->mf_fd >= 0 && close(mfp->mf_fd) < 0) {
194
189
      EMSG(_(e_swapclose));
195
190
  }
196
 
  if (del_file && mfp->mf_fname != NULL)
 
191
  if (del_file && mfp->mf_fname != NULL) {
197
192
    os_remove((char *)mfp->mf_fname);
 
193
  }
 
194
 
198
195
  // free entries in used list
199
 
  for (hp = mfp->mf_used_first; hp != NULL; hp = nextp) {
 
196
  for (bhdr_T *hp = mfp->mf_used_first, *nextp; hp != NULL; hp = nextp) {
200
197
    total_mem_used -= hp->bh_page_count * mfp->mf_page_size;
201
198
    nextp = hp->bh_next;
202
199
    mf_free_bhdr(hp);
203
200
  }
204
 
  while (mfp->mf_free_first != NULL)    // free entries in free list
 
201
  while (mfp->mf_free_first != NULL) {  // free entries in free list
205
202
    xfree(mf_rem_free(mfp));
 
203
  }
206
204
  mf_hash_free(&mfp->mf_hash);
207
205
  mf_hash_free_all(&mfp->mf_trans);     // free hashtable and its items
208
 
  xfree(mfp->mf_fname);
209
 
  xfree(mfp->mf_ffname);
 
206
  mf_free_fnames(mfp);
210
207
  xfree(mfp);
211
208
}
212
209
 
216
213
void mf_close_file(buf_T *buf, bool getlines)
217
214
{
218
215
  memfile_T *mfp = buf->b_ml.ml_mfp;
219
 
  if (mfp == NULL || mfp->mf_fd < 0)     // nothing to close
 
216
  if (mfp == NULL || mfp->mf_fd < 0) {   // nothing to close
220
217
    return;
 
218
  }
221
219
 
222
220
  if (getlines) {
223
221
    // get all blocks in memory by accessing all lines (clumsy!)
224
222
    mf_dont_release = true;
225
 
    for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum)
 
223
    for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum) {
226
224
      (void)ml_get_buf(buf, lnum, false);
 
225
    }
227
226
    mf_dont_release = false;
228
227
    // TODO(elmart): should check if all blocks are really in core
229
228
  }
230
229
 
231
 
  if (close(mfp->mf_fd) < 0)             // close the file
 
230
  if (close(mfp->mf_fd) < 0) {           // close the file
232
231
    EMSG(_(e_swapclose));
 
232
  }
233
233
  mfp->mf_fd = -1;
234
234
 
235
235
  if (mfp->mf_fname != NULL) {
236
236
    os_remove((char *)mfp->mf_fname);    // delete the swap file
237
 
    xfree(mfp->mf_fname);
238
 
    xfree(mfp->mf_ffname);
239
 
    mfp->mf_fname = NULL;
240
 
    mfp->mf_ffname = NULL;
 
237
    mf_free_fnames(mfp);
241
238
  }
242
239
}
243
240
 
390
387
/// Signal block as no longer used (may put it in the free list).
391
388
void mf_free(memfile_T *mfp, bhdr_T *hp)
392
389
{
393
 
  xfree(hp->bh_data);            // free data
 
390
  xfree(hp->bh_data);           // free data
394
391
  mf_rem_hash(mfp, hp);         // get *hp out of the hash list
395
392
  mf_rem_used(mfp, hp);         // get *hp out of the used list
396
393
  if (hp->bh_bnum < 0) {
397
 
    xfree(hp);                   // don't want negative numbers in free list
 
394
    xfree(hp);                  // don't want negative numbers in free list
398
395
    mfp->mf_neg_count--;
399
396
  } else {
400
397
    mf_ins_free(mfp, hp);       // put *hp in the free list
475
472
/// These are blocks that need to be written to a newly created swapfile.
476
473
void mf_set_dirty(memfile_T *mfp)
477
474
{
478
 
  bhdr_T *hp;
479
 
  for (hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev)
480
 
    if (hp->bh_bnum > 0)
 
475
  for (bhdr_T *hp = mfp->mf_used_last; hp != NULL; hp = hp->bh_prev) {
 
476
    if (hp->bh_bnum > 0) {
481
477
      hp->bh_flags |= BH_DIRTY;
 
478
    }
 
479
  }
482
480
  mfp->mf_dirty = true;
483
481
}
484
482
 
506
504
  hp->bh_next = mfp->mf_used_first;
507
505
  mfp->mf_used_first = hp;
508
506
  hp->bh_prev = NULL;
509
 
  if (hp->bh_next == NULL)      // list was empty, adjust last pointer
 
507
  if (hp->bh_next == NULL) {    // list was empty, adjust last pointer
510
508
    mfp->mf_used_last = hp;
511
 
  else
 
509
  } else {
512
510
    hp->bh_next->bh_prev = hp;
 
511
  }
513
512
  mfp->mf_used_count += hp->bh_page_count;
514
513
  total_mem_used += hp->bh_page_count * mfp->mf_page_size;
515
514
}
615
614
  FOR_ALL_BUFFERS(buf) {
616
615
    memfile_T *mfp = buf->b_ml.ml_mfp;
617
616
    if (mfp != NULL) {
618
 
      // If no swap file yet, may open one.
619
 
      if (mfp->mf_fd < 0 && buf->b_may_swap)
 
617
      // If no swap file yet, try to open one.
 
618
      if (mfp->mf_fd < 0 && buf->b_may_swap) {
620
619
        ml_open_file(buf);
 
620
      }
621
621
 
622
622
      // Flush as many blocks as possible, only if there is a swapfile.
623
623
      if (mfp->mf_fd >= 0) {
752
752
    else
753
753
      page_count = hp2->bh_page_count;
754
754
    size = page_size * page_count;
755
 
    if (mf_write_block(mfp, hp2 == NULL ? hp : hp2, offset, size) == FAIL) {
 
755
    void *data = (hp2 == NULL) ? hp->bh_data : hp2->bh_data;
 
756
    if ((unsigned)write_eintr(mfp->mf_fd, data, size) != size) {
756
757
      /// Avoid repeating the error message, this mostly happens when the
757
758
      /// disk is full. We give the message again only after a successful
758
759
      /// write or when hitting a key. We keep on trying, in case some
773
774
  return OK;
774
775
}
775
776
 
776
 
/// Write block to memfile's file.
777
 
///
778
 
/// @return  OK    On success.
779
 
///          FAIL  On failure.
780
 
static int mf_write_block(memfile_T *mfp, bhdr_T *hp,
781
 
                          off_t offset, unsigned size)
782
 
{
783
 
  void *data = hp->bh_data;
784
 
  int result = OK;
785
 
  if ((unsigned)write_eintr(mfp->mf_fd, data, size) != size)
786
 
    result = FAIL;
787
 
  return result;
788
 
}
789
 
 
790
777
/// Make block number positive and add it to the translation list.
791
778
///
792
779
/// @return  OK    On success.
856
843
  return new_bnum;
857
844
}
858
845
 
859
 
/// Set full file name of memfile's swapfile, out of simple file name and some
860
 
/// other considerations.
 
846
/// Frees mf_fname and mf_ffname.
 
847
void mf_free_fnames(memfile_T *mfp)
 
848
{
 
849
  xfree(mfp->mf_fname);
 
850
  xfree(mfp->mf_ffname);
 
851
  mfp->mf_fname = NULL;
 
852
  mfp->mf_ffname = NULL;
 
853
}
 
854
 
 
855
/// Set the simple file name and the full file name of memfile's swapfile, out
 
856
/// of simple file name and some other considerations.
861
857
///
862
858
/// Only called when creating or renaming the swapfile. Either way it's a new
863
859
/// name so we must work out the full path name.
864
 
void mf_set_ffname(memfile_T *mfp)
 
860
void mf_set_fnames(memfile_T *mfp, char_u *fname)
865
861
{
 
862
  mfp->mf_fname = fname;
866
863
  mfp->mf_ffname = (char_u *)FullName_save((char *)mfp->mf_fname, false);
867
864
}
868
865
 
878
875
  }
879
876
}
880
877
 
881
 
/// Return TRUE if there are any translations pending for memfile.
 
878
/// Return true if there are any translations pending for memfile.
882
879
bool mf_need_trans(memfile_T *mfp)
883
880
{
884
881
  return mfp->mf_fname != NULL && mfp->mf_neg_count > 0;
889
886
/// "fname" must be in allocated memory, and is consumed (also when error).
890
887
///
891
888
/// @param  flags  Flags for open().
892
 
static void mf_do_open(memfile_T *mfp, char_u *fname, int flags)
 
889
/// @return A bool indicating success of the `open` call.
 
890
static bool mf_do_open(memfile_T *mfp, char_u *fname, int flags)
893
891
{
894
892
  // fname cannot be NameBuff, because it must have been allocated.
895
 
  mfp->mf_fname = fname;
896
 
  mf_set_ffname(mfp);
 
893
  mf_set_fnames(mfp, fname);
897
894
 
898
895
  /// Extra security check: When creating a swap file it really shouldn't
899
896
  /// exist yet. If there is a symbolic link, this is most likely an attack.
904
901
    EMSG(_("E300: Swap file already exists (symlink attack?)"));
905
902
  } else {
906
903
    // try to open the file
907
 
    flags |= O_NOFOLLOW;
908
 
    mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags);
 
904
    mfp->mf_fd = mch_open_rw((char *)mfp->mf_fname, flags | O_NOFOLLOW);
909
905
  }
910
906
 
911
907
  // If the file cannot be opened, use memory only
912
908
  if (mfp->mf_fd < 0) {
913
 
    xfree(mfp->mf_fname);
914
 
    xfree(mfp->mf_ffname);
915
 
    mfp->mf_fname = NULL;
916
 
    mfp->mf_ffname = NULL;
917
 
  } else {
 
909
    mf_free_fnames(mfp);
 
910
    return false;
 
911
  }
 
912
 
918
913
#ifdef HAVE_FD_CLOEXEC
919
 
    int fdflags = fcntl(mfp->mf_fd, F_GETFD);
920
 
    if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0)
921
 
      fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
 
914
  int fdflags = fcntl(mfp->mf_fd, F_GETFD);
 
915
  if (fdflags >= 0 && (fdflags & FD_CLOEXEC) == 0) {
 
916
    fcntl(mfp->mf_fd, F_SETFD, fdflags | FD_CLOEXEC);
 
917
  }
922
918
#endif
923
919
#ifdef HAVE_SELINUX
924
 
    mch_copy_sec(fname, mfp->mf_fname);
 
920
  mch_copy_sec(fname, mfp->mf_fname);
925
921
#endif
926
 
  }
 
922
 
 
923
  return true;
927
924
}
928
925
 
929
926
//
948
945
/// The hash table must not be used again without another mf_hash_init() call.
949
946
static void mf_hash_free(mf_hashtab_T *mht)
950
947
{
951
 
  if (mht->mht_buckets != mht->mht_small_buckets)
 
948
  if (mht->mht_buckets != mht->mht_small_buckets) {
952
949
    xfree(mht->mht_buckets);
 
950
  }
953
951
}
954
952
 
955
953
/// Free the array of a hash table and all the items it contains.
956
954
static void mf_hash_free_all(mf_hashtab_T *mht)
957
955
{
958
 
  mf_hashitem_T *next;
959
 
 
960
 
  for (size_t idx = 0; idx <= mht->mht_mask; idx++)
 
956
  for (size_t idx = 0; idx <= mht->mht_mask; idx++) {
 
957
    mf_hashitem_T *next;
961
958
    for (mf_hashitem_T *mhi = mht->mht_buckets[idx]; mhi != NULL; mhi = next) {
962
959
      next = mhi->mhi_next;
963
960
      xfree(mhi);
964
961
    }
 
962
  }
965
963
 
966
964
  mf_hash_free(mht);
967
965
}