~ubuntu-branches/ubuntu/quantal/open-vm-tools/quantal-201210021442

« back to all changes in this revision

Viewing changes to lib/misc/util_misc.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2011-03-31 14:20:05 UTC
  • mfrom: (1.4.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110331142005-3n9red91p7ogkweo
Tags: 2011.03.28-387002-0ubuntu1
* Merge latest upstream git tag.  This has the unlocked_ioctl change
  needed to fix dkms build failures (LP: #727342)
* Changes in debian/rules:
  - work around a bug in toolbox/Makefile, where install-exec-hook is
    not happening.  This needs to get fixed the right way.
  - don't install 'vmware-user' which seems to no longer exist
  - move /etc/xdg into open-vm-toolbox (which should be done using .install)
* debian/open-vm-tools.init: add 'modprobe [-r] vmblock'. (LP: #332323)
* debian/rules and debian/open-vm-toolbox.lintian-overrides:
  - Make vmware-user-suid-wrapper suid-root (LP: #332323)

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
#include "su.h"
61
61
#include "escape.h"
62
62
#include "posix.h"
 
63
#include "unicode.h"
63
64
 
64
65
#if defined(_WIN32)
65
66
#include "win32u.h"
455
456
Util_ThreadID
456
457
Util_GetCurrentThreadId(void)
457
458
{
458
 
#if defined(linux)
 
459
#if defined(linux) || defined __ANDROID__
459
460
   /*
460
461
    * It is possible that two threads can enter gettid() path simultaneously,
461
462
    * both eventually clearing useTid to zero. It does not matter - only
506
507
#endif
507
508
}
508
509
 
 
510
 
 
511
/*
 
512
 *-----------------------------------------------------------------------------
 
513
 *
 
514
 * UtilIsAlphaOrNum --
 
515
 *
 
516
 *      Checks if character is a numeric digit or a letter of the 
 
517
 *      english alphabet.
 
518
 *
 
519
 * Results:
 
520
 *      Returns TRUE if character is a digit or a letter, FALSE otherwise.
 
521
 *
 
522
 * Side effects:
 
523
 *           None.
 
524
 *
 
525
 *-----------------------------------------------------------------------------
 
526
 */
 
527
 
 
528
static Bool
 
529
UtilIsAlphaOrNum(char ch) //IN
 
530
{
 
531
   if ((ch >= '0' && ch <= '9') ||
 
532
       (ch >= 'a' && ch <= 'z') ||
 
533
       (ch >= 'A' && ch <= 'Z')) {
 
534
      return TRUE;
 
535
   } else {
 
536
      return FALSE;
 
537
   }
 
538
}
 
539
 
 
540
 
 
541
#ifndef _WIN32
 
542
 
 
543
/*
 
544
 *-----------------------------------------------------------------------------
 
545
 *
 
546
 * UtilGetHomeDirectory --
 
547
 *
 
548
 *      Unicode wrapper for posix getpwnam call for working directory.
 
549
 *
 
550
 * Results:
 
551
 *      Returns initial working directory or NULL if it fails.
 
552
 *
 
553
 * Side effects:
 
554
 *           None.
 
555
 *
 
556
 *-----------------------------------------------------------------------------
 
557
 */
 
558
 
 
559
static char *
 
560
UtilGetHomeDirectory(const char *name) // IN: user name
 
561
{
 
562
   char *dir;
 
563
   struct passwd *pwd;
 
564
 
 
565
   ASSERT(name);
 
566
 
 
567
   pwd = Posix_Getpwnam(name);
 
568
   if (pwd && pwd->pw_dir) {
 
569
      dir = Util_SafeStrdup(pwd->pw_dir);
 
570
   } else {
 
571
      dir = NULL;
 
572
   }
 
573
   endpwent();
 
574
 
 
575
   return dir;
 
576
}
 
577
 
 
578
 
 
579
/*
 
580
 *-----------------------------------------------------------------------------
 
581
 *
 
582
 * UtilGetLoginName --
 
583
 *
 
584
 *      Unicode wrapper for posix getpwnam call for working directory.
 
585
 *
 
586
 * Results:
 
587
 *      Returns user's login name or NULL if it fails.
 
588
 *
 
589
 * Side effects:
 
590
 *           None.
 
591
 *
 
592
 *-----------------------------------------------------------------------------
 
593
 */
 
594
 
 
595
static char *
 
596
UtilGetLoginName(int uid) //IN: user id
 
597
{
 
598
   char *name;
 
599
   struct passwd *pwd;
 
600
 
 
601
   pwd = Posix_Getpwuid(uid);
 
602
   if (pwd && pwd->pw_name) {
 
603
      name = Util_SafeStrdup(pwd->pw_name);
 
604
   } else {
 
605
      name = NULL;
 
606
   }
 
607
   endpwent();
 
608
 
 
609
   return name;
 
610
}
 
611
 
 
612
 
 
613
/*
 
614
 *----------------------------------------------------------------------
 
615
 *
 
616
 * UtilDoTildeSubst --
 
617
 *
 
618
 *      Given a string following a tilde, this routine returns the
 
619
 *      corresponding home directory.
 
620
 *
 
621
 * Results:
 
622
 *      The result is a pointer to a static string containing the home
 
623
 *      directory in native format.  The returned string is a newly
 
624
 *      allocated string which may/must be freed by the caller
 
625
 *
 
626
 * Side effects:
 
627
 *      Information may be left in resultPtr.
 
628
 *
 
629
 * Credit: derived from J.K.Ousterhout's Tcl
 
630
 *----------------------------------------------------------------------
 
631
 */
 
632
 
 
633
static Unicode
 
634
UtilDoTildeSubst(Unicode user)  // IN - name of user
 
635
{
 
636
   Unicode str = NULL;
 
637
 
 
638
   if (*user == '\0') {
 
639
      str = Unicode_Duplicate(Posix_Getenv("HOME"));
 
640
      if (str == NULL) {
 
641
         Log("Could not expand environment variable HOME.\n");
 
642
      }
 
643
   } else {
 
644
      str = UtilGetHomeDirectory(user);
 
645
      if (str == NULL) {
 
646
         Log("Could not get information for user '%s'.\n", user);
 
647
      }
 
648
   }
 
649
   return str;
 
650
}
 
651
 
 
652
#endif // !_WIN32
 
653
 
 
654
 
 
655
/*
 
656
 *----------------------------------------------------------------------
 
657
 *
 
658
 * Util_ExpandString --
 
659
 *
 
660
 *      converts the strings by expanding "~", "~user" and environment
 
661
 *      variables
 
662
 *
 
663
 * Results:
 
664
 *
 
665
 *      Return a newly allocated string.  The caller is responsible
 
666
 *      for deallocating it.
 
667
 *
 
668
 *      Return NULL in case of error.
 
669
 *
 
670
 * Side effects:
 
671
 *      memory allocation
 
672
 *
 
673
 * Bugs:
 
674
 *      the handling of enviroment variable references is very
 
675
 *      simplistic: there can be only one in a pathname segment
 
676
 *      and it must appear last in the string
 
677
 *
 
678
 *----------------------------------------------------------------------
 
679
 */
 
680
 
 
681
#define UTIL_MAX_PATH_CHUNKS 100
 
682
 
 
683
Unicode
 
684
Util_ExpandString(ConstUnicode fileName) // IN  file path to expand
 
685
{
 
686
   Unicode copy = NULL;
 
687
   Unicode result = NULL;
 
688
   int nchunk = 0;
 
689
   char *chunks[UTIL_MAX_PATH_CHUNKS];
 
690
   int chunkSize[UTIL_MAX_PATH_CHUNKS];
 
691
   Bool freeChunk[UTIL_MAX_PATH_CHUNKS];
 
692
   char *cp;
 
693
   int i;
 
694
 
 
695
   ASSERT(fileName);
 
696
 
 
697
   copy = Unicode_Duplicate(fileName);
 
698
 
 
699
   /*
 
700
    * quick exit
 
701
    */
 
702
   if (!Unicode_StartsWith(fileName, "~") && 
 
703
       Unicode_Find(fileName, "$") == UNICODE_INDEX_NOT_FOUND) {
 
704
      return copy;
 
705
   }
 
706
 
 
707
   /*
 
708
    * XXX Because the rest part of code depends pretty heavily from
 
709
    *     character pointer operations we want to leave it as-is and
 
710
    *     don't want to re-work it with using unicode library. However
 
711
    *     it's acceptable only until our Unicode type is utf-8 and
 
712
    *     until code below works correctly with utf-8.
 
713
    */
 
714
 
 
715
   /*
 
716
    * Break string into nice chunks for separate expansion.
 
717
    *
 
718
    * The rule for terminating a ~ expansion is historical.  -- edward
 
719
    */
 
720
 
 
721
   nchunk = 0;
 
722
   for (cp = copy; *cp;) {
 
723
      size_t len;
 
724
      if (*cp == '$') {
 
725
         char *p;
 
726
         for (p = cp + 1; UtilIsAlphaOrNum(*p) || *p == '_'; p++) {
 
727
         }
 
728
         len = p - cp;
 
729
#if !defined(_WIN32)
 
730
      } else if (cp == copy && *cp == '~') {
 
731
         len = strcspn(cp, DIRSEPS);
 
732
#endif
 
733
      } else {
 
734
         len = strcspn(cp, "$");
 
735
      }
 
736
      if (nchunk >= UTIL_MAX_PATH_CHUNKS) {
 
737
         Log("%s: Filename \"%s\" has too many chunks.\n", __FUNCTION__,
 
738
             UTF8(fileName));
 
739
         goto out;
 
740
      }
 
741
      chunks[nchunk] = cp;
 
742
      chunkSize[nchunk] = len;
 
743
      freeChunk[nchunk] = FALSE;
 
744
      nchunk++;
 
745
      cp += len;
 
746
   }
 
747
 
 
748
   /*
 
749
    * Expand leanding ~
 
750
    */
 
751
 
 
752
#if !defined(_WIN32)
 
753
   if (chunks[0][0] == '~') {
 
754
      char save = (cp = chunks[0])[chunkSize[0]];
 
755
      cp[chunkSize[0]] = 0;
 
756
      ASSERT(!freeChunk[0]);
 
757
      chunks[0] = UtilDoTildeSubst(chunks[0] + 1);
 
758
      cp[chunkSize[0]] = save;
 
759
      if (chunks[0] == NULL) {
 
760
         /* It could not be expanded, therefore leave as original. */
 
761
         chunks[0] = cp;
 
762
      } else {
 
763
         /* It was expanded, so adjust the chunks. */
 
764
         chunkSize[0] = strlen(chunks[0]);
 
765
         freeChunk[0] = TRUE;
 
766
      }
 
767
   }
 
768
#endif
 
769
 
 
770
   /*
 
771
    * Expand $
 
772
    */
 
773
 
 
774
   for (i = 0; i < nchunk; i++) {
 
775
      char save;
 
776
      Unicode expand = NULL;
 
777
      char buf[100];
 
778
#if defined(_WIN32)
 
779
      utf16_t bufW[100];
 
780
#endif
 
781
      cp = chunks[i];
 
782
 
 
783
      if (*cp != '$' || chunkSize[i] == 1) {
 
784
 
 
785
         /*
 
786
          * Skip if the chuck has only the $ character.
 
787
          * $ will be kept as a part of the pathname.
 
788
          */
 
789
 
 
790
         continue;
 
791
      }
 
792
 
 
793
      save = cp[chunkSize[i]];
 
794
      cp[chunkSize[i]] = 0;
 
795
 
 
796
      /*
 
797
       * $PID and $USER are interpreted specially.
 
798
       * Others are just getenv().
 
799
       */
 
800
 
 
801
      expand = Unicode_Duplicate(Posix_Getenv(cp + 1));
 
802
      if (expand != NULL) {
 
803
      } else if (strcasecmp(cp + 1, "PID") == 0) {
 
804
         Str_Snprintf(buf, sizeof buf, "%"FMTPID, getpid());
 
805
         expand = Util_SafeStrdup(buf);
 
806
      } else if (strcasecmp(cp + 1, "USER") == 0) {
 
807
#if !defined(_WIN32)
 
808
         int uid = getuid();
 
809
         expand = UtilGetLoginName(uid);
 
810
#else
 
811
         DWORD n = ARRAYSIZE(bufW);
 
812
         if (GetUserNameW(bufW, &n)) {
 
813
            expand = Unicode_AllocWithUTF16(bufW);
 
814
         }
 
815
#endif
 
816
         if (expand == NULL) {
 
817
            expand = Unicode_Duplicate("unknown");
 
818
         }
 
819
      } else {
 
820
         Warning("Environment variable '%s' not defined in '%s'.\n",
 
821
                 cp + 1, fileName);
 
822
#if !defined(_WIN32)
 
823
         /*
 
824
          * Strip off the env variable string from the pathname.
 
825
          */
 
826
 
 
827
         expand = Unicode_Duplicate("");
 
828
 
 
829
#else    // _WIN32
 
830
 
 
831
         /*
 
832
          * The problem is we have really no way to distinguish the caller's
 
833
          * intention is a dollar sign ($) is used as a part of the pathname
 
834
          * or as an environment variable.
 
835
          *
 
836
          * If the token does not expand to an environment variable,
 
837
          * then assume it is a part of the pathname. Do not strip it
 
838
          * off like it is done in linux host (see above)
 
839
          *
 
840
          * XXX   We should also consider using %variable% convention instead
 
841
          *       of $variable for Windows platform.
 
842
          */
 
843
 
 
844
         Str_Strcpy(buf, cp, 100);
 
845
         expand = Unicode_AllocWithUTF8(buf);
 
846
#endif
 
847
      }
 
848
 
 
849
      cp[chunkSize[i]] = save;
 
850
 
 
851
      ASSERT(expand != NULL);
 
852
      ASSERT(!freeChunk[i]);
 
853
      chunks[i] = expand;
 
854
      if (chunks[i] == NULL) {
 
855
         Log("%s: Cannot allocate memory to expand \"%s\" in \"%s\".\n",
 
856
             __FUNCTION__, expand, UTF8(fileName));
 
857
         goto out;
 
858
      }
 
859
      chunkSize[i] = strlen(expand);
 
860
      freeChunk[i] = TRUE;
 
861
   }
 
862
 
 
863
   /*
 
864
    * Put all the chunks back together.
 
865
    */
 
866
 
 
867
   {
 
868
      int size = 1;     // 1 for the terminating null
 
869
      for (i = 0; i < nchunk; i++) {
 
870
         size += chunkSize[i];
 
871
      }
 
872
      result = malloc(size);
 
873
   }
 
874
   if (result == NULL) {
 
875
      Log("%s: Cannot allocate memory for the expansion of \"%s\".\n",
 
876
          __FUNCTION__, UTF8(fileName));
 
877
      goto out;
 
878
   }
 
879
   cp = result;
 
880
   for (i = 0; i < nchunk; i++) {
 
881
      memcpy(cp, chunks[i], chunkSize[i]);
 
882
      cp += chunkSize[i];
 
883
   }
 
884
   *cp = 0;
 
885
 
 
886
out:
 
887
   /*
 
888
    * Clean up and return.
 
889
    */
 
890
 
 
891
   for (i = 0; i < nchunk; i++) {
 
892
      if (freeChunk[i]) {
 
893
         free(chunks[i]);
 
894
      }
 
895
   }
 
896
   free(copy);
 
897
 
 
898
   return result;
 
899
}
 
900
 
509
901
#endif // N_PLAT_NLM
510