View | Details | Raw Unified | Return to issue 89730
Collapse All | Expand All

(-)sal/osl/unx/file_url.cxx (-291 / +24 lines)
Lines 446-751 oslFileError osl_getSystemPathFromFileURL_Ex( Link Here
446
    return osl_error;
446
    return osl_error;
447
}
447
}
448
448
449
namespace /* private */
449
/******************************************************
450
 * Resolve the paths if they exist. The resulting 
451
 * path must not exceed PATH_MAX else 
452
 * osl_File_E_NAMETOOLONG is the result
453
 ******************************************************/
454
 
455
static oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved, rtl::OUString& resolved)
450
{
456
{
457
	char unresolved_path[PATH_MAX];
458
	char resolved_path[PATH_MAX];
451
459
452
	/******************************************************
460
	if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), unresolved.getStr(), unresolved.getLength()))
453
	 * Helper function, return a pinter to the final '\0'
461
		return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
454
	 * of a string
455
	 ******************************************************/
456
 
457
	sal_Unicode* ustrtoend(sal_Unicode* pStr)
458
	{		
459
		return (pStr + rtl_ustr_getLength(pStr));
460
	}
461
	
462
	/*********************************************
463
462
464
	 ********************************************/
463
	if (realpath(unresolved_path, resolved_path))
465
	sal_Unicode* ustrcpy(const sal_Unicode* s, sal_Unicode* d)
466
	{
464
	{
467
		const sal_Unicode* sc = s;
465
		sal_Unicode path[PATH_MAX];
468
		sal_Unicode*       dc = d;
466
		if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))
469
		
467
			return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
470
		while ((*dc++ = *sc++))
471
			/**/;
472
			
473
		return d;
474
	}
475
	
476
	/*********************************************
477
468
478
	 ********************************************/
469
		resolved = rtl::OUString(path, rtl_ustr_getLength(path));
479
	 
470
		return osl_File_E_None;
480
	sal_Unicode* ustrncpy(const sal_Unicode* s, sal_Unicode* d, unsigned int n)
481
	{
482
		const sal_Unicode* sc = s;
483
		sal_Unicode*       dc = d;
484
		unsigned int       i  = n;		
485
		
486
		while (i--)	
487
			*dc++ = *sc++;
488
		
489
		if (n)
490
			*dc = 0;
491
			
492
		return d;
493
	}
471
	}
494
	
472
	else
495
	/*********************************************
496
497
	 ********************************************/
498
	 
499
	sal_Unicode* ustrchrcat(const sal_Unicode chr, sal_Unicode* d)
500
	{
473
	{
501
		sal_Unicode* p = ustrtoend(d);
474
		if (EACCES != errno && ENOTDIR != errno && ENOENT != errno)
502
		*p++ = chr;
475
			return oslTranslateFileError(OSL_FET_ERROR, errno);
503
		*p   = 0;		
504
		return d;	
505
	}
476
	}
506
477
507
	/*********************************************
478
	// the 'unresolved' does not exist, let's just copy it to 'resolved'
508
479
	resolved = unresolved;
509
	 ********************************************/
480
	return osl_File_E_None;
510
	 
481
}
511
	sal_Unicode* ustrcat(const sal_Unicode* s, sal_Unicode* d)
512
	{
513
		sal_Unicode* dc = ustrtoend(d);					
514
		ustrcpy(s, dc);		
515
		return d;
516
	}	
517
518
	/******************************************************
519
	 *
520
	 ******************************************************/
521
 
522
	bool _islastchr(sal_Unicode* pStr, sal_Unicode Chr)
523
	{
524
   		sal_Unicode* p = ustrtoend(pStr);
525
	   	if (p > pStr)
526
       		p--;
527
	   	return (*p == Chr);  
528
	}
529
530
	/******************************************************
531
	 * Ensure that the given string has the specified last 
532
	 * character if necessary append it
533
	 ******************************************************/
534
 
535
	sal_Unicode* _strensurelast(sal_Unicode* pStr, sal_Unicode Chr)
536
	{
537
    	if (!_islastchr(pStr, Chr))
538
        	ustrchrcat(Chr, pStr);
539
	    return pStr;
540
	}	
541
542
	/******************************************************
543
	 * Remove the last part of a path, a path that has 
544
	 * only a '/' or no '/' at all will be returned
545
	 * unmodified 
546
	 ******************************************************/
547
 
548
	sal_Unicode* _rmlastpathtoken(sal_Unicode* aPath)
549
	{
550
		/* 	we always may skip -2 because we
551
	   		may at least stand on a '/' but
552
		   	either there is no other character
553
		   	before this '/' or it's another 
554
	   		character than the '/' 
555
		*/
556
		sal_Unicode* p = ustrtoend(aPath) - 2;
557
558
		// move back to the next path separator
559
		// or to the start of the string
560
		while ((p > aPath) && (*p != UNICHAR_SLASH))
561
			p--;
562
563
		if (p >= aPath)
564
		{
565
    		if (UNICHAR_SLASH == *p)
566
    		{
567
				p++;
568
			   *p = '\0';
569
    		}
570
    		else
571
    		{
572
		   		*p = '\0';
573
    		}
574
		}
575
    
576
	    return aPath;
577
	}
578
579
	/******************************************************
580
	 * 
581
	 ******************************************************/
582
 
583
	oslFileError _osl_resolvepath(
584
    	/*inout*/ sal_Unicode* path, 
585
	    /*inout*/ sal_Unicode* current_pos, 
586
    	/*inout*/ bool* failed)
587
	{
588
    	oslFileError ferr = osl_File_E_None;
589
    
590
	    if (!*failed)
591
    	{
592
			char unresolved_path[PATH_MAX];			
593
			if (!UnicodeToText(unresolved_path, sizeof(unresolved_path), path, rtl_ustr_getLength(path)))
594
				return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
595
				
596
			char resolved_path[PATH_MAX];			
597
		    if (realpath(unresolved_path, resolved_path))
598
			{
599
				if (!TextToUnicode(resolved_path, strlen(resolved_path), path, PATH_MAX))		
600
					return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
601
					
602
				current_pos = ustrtoend(path) - 1;	    					
603
			}
604
			else
605
			{
606
				if (EACCES == errno || ENOTDIR == errno || ENOENT == errno)
607
					*failed = true;
608
				else
609
					ferr = oslTranslateFileError(OSL_FET_ERROR, errno);
610
			}
611
    	}
612
		
613
	    return ferr;
614
	}	
615
616
	/******************************************************
617
	 * Works even with non existing paths. The resulting 
618
	 * path must not exceed PATH_MAX else 
619
	 * osl_File_E_NAMETOOLONG is the result
620
	 ******************************************************/
621
 
622
	oslFileError osl_getAbsoluteFileURL_impl_(const rtl::OUString& unresolved_path, rtl::OUString& resolved_path)
623
	{
624
		// the given unresolved path must not exceed PATH_MAX 
625
	    if (unresolved_path.getLength() >= (PATH_MAX - 2))
626
    	    return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
627
		
628
	    sal_Unicode        path_resolved_so_far[PATH_MAX];	    
629
	    const sal_Unicode* punresolved = unresolved_path.getStr(); 
630
		sal_Unicode*       presolvedsf = path_resolved_so_far;
631
    
632
	    // reserve space for leading '/' and trailing '\0'
633
	    // do not exceed this limit 
634
    	sal_Unicode* sentinel = path_resolved_so_far + PATH_MAX - 2; 
635
    
636
	    // if realpath fails with error ENOTDIR, EACCES or ENOENT
637
	    // we will not call it again, because _osl_realpath should also
638
    	// work with non existing directories etc. 
639
	    bool realpath_failed = false;
640
    	oslFileError ferr;
641
              
642
	    path_resolved_so_far[0] = '\0';
643
    
644
    	while (*punresolved != '\0')
645
    	{
646
        	// ignore '/.' , skip one part back when '/..' 
647
	
648
	        if ((UNICHAR_DOT == *punresolved) && (UNICHAR_SLASH == *presolvedsf))
649
    	    {            
650
        	    if ('\0' == *(punresolved + 1))
651
            	{
652
                	punresolved++;
653
	                continue;
654
    	        }
655
        	    else if (UNICHAR_SLASH == *(punresolved + 1))
656
            	{
657
                	punresolved += 2;
658
	                continue;
659
    	        }            
660
        	    else if ((UNICHAR_DOT == *(punresolved + 1)) && ('\0' == *(punresolved + 2) || (UNICHAR_SLASH == *(punresolved + 2))))
661
            	{                
662
                	_rmlastpathtoken(path_resolved_so_far);
663
                
664
	                presolvedsf = ustrtoend(path_resolved_so_far) - 1;
665
                
666
    	            if (UNICHAR_SLASH == *(punresolved + 2))
667
        	            punresolved += 3;
668
            	    else
669
                	    punresolved += 2;
670
                    
671
	                continue;
672
    	        }                    
673
        	    else // a file or directory name may start with '.' 
674
            	{
675
                	if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
676
                    	return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
677
                    
678
	                ustrchrcat(*punresolved++, path_resolved_so_far); 
679
                
680
    	            if ('\0' == *punresolved && !realpath_failed)
681
        	        {
682
						ferr = _osl_resolvepath(
683
							path_resolved_so_far, 
684
							presolvedsf, 
685
							&realpath_failed);
686
					
687
						if (osl_File_E_None != ferr)
688
			    			return ferr;
689
            	    }
690
            	}
691
        	}
692
	        else if (UNICHAR_SLASH == *punresolved)
693
    	    {  
694
				if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
695
            	    return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
696
                        
697
	            ustrchrcat(*punresolved++, path_resolved_so_far); 
698
            
699
    	        if (!realpath_failed)
700
        	    {                
701
            	    ferr = _osl_resolvepath(
702
						path_resolved_so_far, 
703
						presolvedsf, 
704
						&realpath_failed);
705
		    
706
					if (osl_File_E_None != ferr)
707
						return ferr;
708
				
709
					if (!_islastchr(path_resolved_so_far, UNICHAR_SLASH))
710
					{
711
	    				if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
712
							return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
713
					
714
						ustrchrcat(UNICHAR_SLASH, path_resolved_so_far); 
715
					}
716
            	}
717
        	}
718
	        else // any other character
719
    	    {
720
        	    if ((presolvedsf = ustrtoend(path_resolved_so_far)) > sentinel)
721
            	    return oslTranslateFileError(OSL_FET_ERROR, ENAMETOOLONG);
722
                
723
	            ustrchrcat(*punresolved++, path_resolved_so_far); 
724
            
725
    	        if ('\0' == *punresolved && !realpath_failed)
726
        	    {            
727
            	    ferr = _osl_resolvepath(
728
						path_resolved_so_far, 
729
						presolvedsf, 
730
						&realpath_failed);
731
		    
732
					if (osl_File_E_None != ferr)
733
						return ferr;
734
            	}
735
        	}
736
    	}
737
738
		sal_Int32 len = rtl_ustr_getLength(path_resolved_so_far);
739
		
740
	    OSL_ASSERT(len < PATH_MAX);
741
        
742
    	resolved_path = rtl::OUString(path_resolved_so_far, len);
743
		
744
	    return osl_File_E_None;
745
	}
746
747
} // end namespace private
748
749
482
750
/******************************************************
483
/******************************************************
751
 * osl_getAbsoluteFileURL
484
 * osl_getAbsoluteFileURL

Return to issue 89730