~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/libsvn_fs_fs/dag.c

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
#include "svn_props.h"
29
29
#include "svn_pools.h"
30
30
 
 
31
#include "cached_data.h"
31
32
#include "dag.h"
32
33
#include "fs.h"
33
 
#include "key-gen.h"
34
34
#include "fs_fs.h"
35
35
#include "id.h"
 
36
#include "transaction.h"
36
37
 
37
38
#include "../libsvn_fs/fs-loader.h"
38
39
 
159
160
  if (! node->node_revision)
160
161
    {
161
162
      node_revision_t *noderev;
 
163
      apr_pool_t *scratch_pool = svn_pool_create(node->node_pool);
162
164
 
163
165
      SVN_ERR(svn_fs_fs__get_node_revision(&noderev, node->fs,
164
 
                                           node->id, node->node_pool));
 
166
                                           node->id, node->node_pool,
 
167
                                           scratch_pool));
165
168
      node->node_revision = noderev;
 
169
      svn_pool_destroy(scratch_pool);
166
170
    }
167
171
 
168
172
  /* Now NODE->node_revision is set.  */
173
177
 
174
178
svn_boolean_t svn_fs_fs__dag_check_mutable(const dag_node_t *node)
175
179
{
176
 
  return (svn_fs_fs__id_txn_id(svn_fs_fs__dag_get_id(node)) != NULL);
 
180
  return svn_fs_fs__id_is_txn(svn_fs_fs__dag_get_id(node));
177
181
}
178
182
 
179
183
 
312
316
{
313
317
  svn_fs_dirent_t *dirent;
314
318
 
315
 
  SVN_ERR(svn_fs_fs__dag_dir_entry(&dirent, parent, name, scratch_pool));
316
 
  *id_p = dirent ? svn_fs_fs__id_copy(dirent->id, result_pool) : NULL;
 
319
  SVN_ERR(svn_fs_fs__dag_dir_entry(&dirent, parent, name, result_pool,
 
320
                                   scratch_pool));
 
321
  *id_p = dirent ? dirent->id : NULL;
317
322
 
318
323
  return SVN_NO_ERROR;
319
324
}
332
337
          const char *name,
333
338
          const svn_fs_id_t *id,
334
339
          svn_node_kind_t kind,
335
 
          const char *txn_id,
 
340
          const svn_fs_fs__id_part_t *txn_id,
336
341
          apr_pool_t *pool)
337
342
{
338
343
  node_revision_t *parent_noderev;
359
364
           const char *parent_path,
360
365
           const char *name,
361
366
           svn_boolean_t is_dir,
362
 
           const char *txn_id,
 
367
           const svn_fs_fs__id_part_t *txn_id,
363
368
           apr_pool_t *pool)
364
369
{
365
370
  const svn_fs_id_t *new_node_id;
413
418
 
414
419
 
415
420
svn_error_t *
416
 
svn_fs_fs__dag_dir_entries(apr_hash_t **entries,
 
421
svn_fs_fs__dag_dir_entries(apr_array_header_t **entries,
417
422
                           dag_node_t *node,
418
423
                           apr_pool_t *pool)
419
424
{
425
430
    return svn_error_create(SVN_ERR_FS_NOT_DIRECTORY, NULL,
426
431
                            _("Can't get entries of non-directory"));
427
432
 
428
 
  return svn_fs_fs__rep_contents_dir(entries, node->fs, noderev, pool);
 
433
  return svn_fs_fs__rep_contents_dir(entries, node->fs, noderev, pool, pool);
429
434
}
430
435
 
431
436
svn_error_t *
432
437
svn_fs_fs__dag_dir_entry(svn_fs_dirent_t **dirent,
433
438
                         dag_node_t *node,
434
439
                         const char* name,
435
 
                         apr_pool_t *pool)
 
440
                         apr_pool_t *result_pool,
 
441
                         apr_pool_t *scratch_pool)
436
442
{
437
443
  node_revision_t *noderev;
438
444
  SVN_ERR(get_node_revision(&noderev, node));
442
448
                            _("Can't get entries of non-directory"));
443
449
 
444
450
  /* Get a dirent hash for this directory. */
445
 
  return svn_fs_fs__rep_contents_dir_entry(dirent, node->fs,
446
 
                                           noderev, name, pool, pool);
 
451
  return svn_fs_fs__rep_contents_dir_entry(dirent, node->fs, noderev, name,
 
452
                                           result_pool, scratch_pool);
447
453
}
448
454
 
449
455
 
452
458
                         const char *entry_name,
453
459
                         const svn_fs_id_t *id,
454
460
                         svn_node_kind_t kind,
455
 
                         const char *txn_id,
 
461
                         const svn_fs_fs__id_part_t *txn_id,
456
462
                         apr_pool_t *pool)
457
463
{
458
464
  /* Check it's a directory. */
492
498
  return SVN_NO_ERROR;
493
499
}
494
500
 
 
501
svn_error_t *
 
502
svn_fs_fs__dag_has_props(svn_boolean_t *has_props,
 
503
                         dag_node_t *node,
 
504
                         apr_pool_t *scratch_pool)
 
505
{
 
506
  node_revision_t *noderev;
 
507
 
 
508
  SVN_ERR(get_node_revision(&noderev, node));
 
509
 
 
510
  if (! noderev->prop_rep)
 
511
    {
 
512
      *has_props = FALSE; /* Easy out */
 
513
      return SVN_NO_ERROR;
 
514
    }
 
515
 
 
516
  if (svn_fs_fs__id_txn_used(&noderev->prop_rep->txn_id))
 
517
    {
 
518
      /* We are in a commit or something. Check actual properties */
 
519
      apr_hash_t *proplist;
 
520
 
 
521
      SVN_ERR(svn_fs_fs__get_proplist(&proplist, node->fs,
 
522
                                      noderev, scratch_pool));
 
523
 
 
524
      *has_props = proplist ? (0 < apr_hash_count(proplist)) : FALSE;
 
525
    }
 
526
  else
 
527
    {
 
528
      /* Properties are stored as a standard hash stream,
 
529
         always ending with "END\n" (4 bytes) */
 
530
      *has_props = (noderev->prop_rep->expanded_size > 4
 
531
                    || (noderev->prop_rep->expanded_size == 0
 
532
                        && noderev->prop_rep->size > 4));
 
533
    }
 
534
 
 
535
  return SVN_NO_ERROR;
 
536
}
495
537
 
496
538
svn_error_t *
497
539
svn_fs_fs__dag_set_proplist(dag_node_t *node,
606
648
                             svn_revnum_t rev,
607
649
                             apr_pool_t *pool)
608
650
{
609
 
  svn_fs_id_t *root_id;
610
 
 
611
 
  SVN_ERR(svn_fs_fs__rev_get_root(&root_id, fs, rev, pool));
612
 
  return svn_fs_fs__dag_get_node(node_p, fs, root_id, pool);
 
651
  dag_node_t *new_node;
 
652
 
 
653
  /* Construct the node. */
 
654
  new_node = apr_pcalloc(pool, sizeof(*new_node));
 
655
  new_node->fs = fs;
 
656
  SVN_ERR(svn_fs_fs__rev_get_root(&new_node->id, fs, rev, pool, pool));
 
657
 
 
658
  /* Grab the contents so we can inspect the node's kind and created path. */
 
659
  new_node->node_pool = pool;
 
660
 
 
661
  /* Initialize the KIND and CREATED_PATH attributes */
 
662
  new_node->kind = svn_node_dir;
 
663
  new_node->created_path = "/";
 
664
  new_node->fresh_root_predecessor_id = NULL;
 
665
 
 
666
  /* Return a fresh new node */
 
667
  *node_p = new_node;
 
668
  return SVN_NO_ERROR;
613
669
}
614
670
 
615
671
 
616
672
svn_error_t *
617
673
svn_fs_fs__dag_txn_root(dag_node_t **node_p,
618
674
                        svn_fs_t *fs,
619
 
                        const char *txn_id,
 
675
                        const svn_fs_fs__id_part_t *txn_id,
620
676
                        apr_pool_t *pool)
621
677
{
622
678
  const svn_fs_id_t *root_id, *ignored;
629
685
svn_error_t *
630
686
svn_fs_fs__dag_txn_base_root(dag_node_t **node_p,
631
687
                             svn_fs_t *fs,
632
 
                             const char *txn_id,
 
688
                             const svn_fs_fs__id_part_t *txn_id,
633
689
                             apr_pool_t *pool)
634
690
{
635
691
  const svn_fs_id_t *base_root_id, *ignored;
644
700
                           dag_node_t *parent,
645
701
                           const char *parent_path,
646
702
                           const char *name,
647
 
                           const char *copy_id,
648
 
                           const char *txn_id,
 
703
                           const svn_fs_fs__id_part_t *copy_id,
 
704
                           const svn_fs_fs__id_part_t *txn_id,
649
705
                           svn_boolean_t is_parent_copyroot,
650
706
                           apr_pool_t *pool)
651
707
{
668
724
 
669
725
  /* Find the node named NAME in PARENT's entries list if it exists. */
670
726
  SVN_ERR(svn_fs_fs__dag_open(&cur_entry, parent, name, pool, subpool));
 
727
  if (! cur_entry)
 
728
    return svn_error_createf
 
729
      (SVN_ERR_FS_NOT_FOUND, NULL,
 
730
       "Attempted to open non-existent child node '%s'", name);
671
731
 
672
732
  /* Check for mutability in the node we found.  If it's mutable, we
673
733
     don't need to clone it. */
718
778
svn_error_t *
719
779
svn_fs_fs__dag_clone_root(dag_node_t **root_p,
720
780
                          svn_fs_t *fs,
721
 
                          const char *txn_id,
 
781
                          const svn_fs_fs__id_part_t *txn_id,
722
782
                          apr_pool_t *pool)
723
783
{
724
784
  const svn_fs_id_t *base_root_id, *root_id;
745
805
svn_error_t *
746
806
svn_fs_fs__dag_delete(dag_node_t *parent,
747
807
                      const char *name,
748
 
                      const char *txn_id,
 
808
                      const svn_fs_fs__id_part_t *txn_id,
749
809
                      apr_pool_t *pool)
750
810
{
751
811
  node_revision_t *parent_noderev;
840
900
  /* Else it's mutable.  Recurse on directories... */
841
901
  if (node->kind == svn_node_dir)
842
902
    {
843
 
      apr_hash_t *entries;
844
 
      apr_hash_index_t *hi;
 
903
      apr_array_header_t *entries;
 
904
      int i;
 
905
      apr_pool_t *iterpool = svn_pool_create(pool);
845
906
 
846
 
      /* Loop over hash entries */
 
907
      /* Loop over directory entries */
847
908
      SVN_ERR(svn_fs_fs__dag_dir_entries(&entries, node, pool));
848
909
      if (entries)
849
 
        {
850
 
          for (hi = apr_hash_first(pool, entries);
851
 
               hi;
852
 
               hi = apr_hash_next(hi))
853
 
            {
854
 
              svn_fs_dirent_t *dirent = svn__apr_hash_index_val(hi);
 
910
        for (i = 0; i < entries->nelts; ++i)
 
911
          {
 
912
            svn_pool_clear(iterpool);
 
913
            SVN_ERR(svn_fs_fs__dag_delete_if_mutable(fs,
 
914
                          APR_ARRAY_IDX(entries, i, svn_fs_dirent_t *)->id,
 
915
                          iterpool));
 
916
          }
855
917
 
856
 
              SVN_ERR(svn_fs_fs__dag_delete_if_mutable(fs, dirent->id,
857
 
                                                       pool));
858
 
            }
859
 
        }
 
918
      svn_pool_destroy(iterpool);
860
919
    }
861
920
 
862
921
  /* ... then delete the node itself, after deleting any mutable
869
928
                         dag_node_t *parent,
870
929
                         const char *parent_path,
871
930
                         const char *name,
872
 
                         const char *txn_id,
 
931
                         const svn_fs_fs__id_part_t *txn_id,
873
932
                         apr_pool_t *pool)
874
933
{
875
934
  /* Call our little helper function */
882
941
                        dag_node_t *parent,
883
942
                        const char *parent_path,
884
943
                        const char *name,
885
 
                        const char *txn_id,
 
944
                        const svn_fs_fs__id_part_t *txn_id,
886
945
                        apr_pool_t *pool)
887
946
{
888
947
  /* Call our little helper function */
909
968
 
910
969
  /* Get a stream to the contents. */
911
970
  SVN_ERR(svn_fs_fs__get_contents(&contents, file->fs,
912
 
                                  noderev, pool));
 
971
                                  noderev->data_rep, TRUE, pool));
913
972
 
914
973
  *contents_p = contents;
915
974
 
1107
1166
 
1108
1167
  /* The deserializer will use its own pool. */
1109
1168
  svn_temp_serializer__set_null(context,
1110
 
                                (const void * const *)&node->node_pool);
 
1169
                                (const void * const *)&node->node_pool);
1111
1170
 
1112
1171
  /* serialize other sub-structures */
1113
1172
  svn_fs_fs__id_serialize(context, (const svn_fs_id_t **)&node->id);
1164
1223
  SVN_ERR(dir_entry_id_from_node(&node_id, parent, name,
1165
1224
                                 scratch_pool, scratch_pool));
1166
1225
  if (! node_id)
1167
 
    return svn_error_createf
1168
 
      (SVN_ERR_FS_NOT_FOUND, NULL,
1169
 
       "Attempted to open non-existent child node '%s'", name);
 
1226
    {
 
1227
      *child_p = NULL;
 
1228
      return SVN_NO_ERROR;
 
1229
    }
1170
1230
 
1171
1231
  /* Make sure that NAME is a single path component. */
1172
1232
  if (! svn_path_is_single_path_component(name))
1187
1247
                    svn_boolean_t preserve_history,
1188
1248
                    svn_revnum_t from_rev,
1189
1249
                    const char *from_path,
1190
 
                    const char *txn_id,
 
1250
                    const svn_fs_fs__id_part_t *txn_id,
1191
1251
                    apr_pool_t *pool)
1192
1252
{
1193
1253
  const svn_fs_id_t *id;
1195
1255
  if (preserve_history)
1196
1256
    {
1197
1257
      node_revision_t *from_noderev, *to_noderev;
1198
 
      const char *copy_id;
 
1258
      svn_fs_fs__id_part_t copy_id;
1199
1259
      const svn_fs_id_t *src_id = svn_fs_fs__dag_get_id(from_node);
1200
1260
      svn_fs_t *fs = svn_fs_fs__dag_get_fs(from_node);
1201
1261
 
1221
1281
      to_noderev->copyroot_path = NULL;
1222
1282
 
1223
1283
      SVN_ERR(svn_fs_fs__create_successor(&id, fs, src_id, to_noderev,
1224
 
                                          copy_id, txn_id, pool));
 
1284
                                          &copy_id, txn_id, pool));
1225
1285
 
1226
1286
    }
1227
1287
  else  /* don't preserve history */
1242
1302
svn_fs_fs__dag_things_different(svn_boolean_t *props_changed,
1243
1303
                                svn_boolean_t *contents_changed,
1244
1304
                                dag_node_t *node1,
1245
 
                                dag_node_t *node2)
 
1305
                                dag_node_t *node2,
 
1306
                                svn_boolean_t strict,
 
1307
                                apr_pool_t *pool)
1246
1308
{
1247
1309
  node_revision_t *noderev1, *noderev2;
 
1310
  svn_fs_t *fs;
 
1311
  svn_boolean_t same;
1248
1312
 
1249
1313
  /* If we have no place to store our results, don't bother doing
1250
1314
     anything. */
1251
1315
  if (! props_changed && ! contents_changed)
1252
1316
    return SVN_NO_ERROR;
1253
1317
 
 
1318
  fs = svn_fs_fs__dag_get_fs(node1);
 
1319
 
1254
1320
  /* The node revision skels for these two nodes. */
1255
1321
  SVN_ERR(get_node_revision(&noderev1, node1));
1256
1322
  SVN_ERR(get_node_revision(&noderev2, node2));
1257
1323
 
1258
1324
  /* Compare property keys. */
1259
1325
  if (props_changed != NULL)
1260
 
    *props_changed = (! svn_fs_fs__noderev_same_rep_key(noderev1->prop_rep,
1261
 
                                                        noderev2->prop_rep));
 
1326
    {
 
1327
      SVN_ERR(svn_fs_fs__prop_rep_equal(&same, fs, noderev1, noderev2,
 
1328
                                        strict, pool));
 
1329
      *props_changed = !same;
 
1330
    }
1262
1331
 
1263
1332
  /* Compare contents keys. */
1264
1333
  if (contents_changed != NULL)
1265
 
    *contents_changed =
1266
 
      (! svn_fs_fs__noderev_same_rep_key(noderev1->data_rep,
1267
 
                                         noderev2->data_rep));
 
1334
    {
 
1335
      SVN_ERR(svn_fs_fs__file_text_rep_equal(&same, fs, noderev1, noderev2,
 
1336
                                             strict, pool));
 
1337
      *contents_changed = !same;
 
1338
    }
1268
1339
 
1269
1340
  return SVN_NO_ERROR;
1270
1341
}