platform/unix.c
changeset 20 efdde0d21521
parent 17 7337737f5120
child 23 bd6ba9c8717c
equal deleted inserted replaced
19:a0279b57398c 20:efdde0d21521
     4  * Please see the file LICENSE in the source's root directory.
     4  * Please see the file LICENSE in the source's root directory.
     5  *
     5  *
     6  *  This file written by Ryan C. Gordon.
     6  *  This file written by Ryan C. Gordon.
     7  */
     7  */
     8 
     8 
       
     9 #if (defined __STRICT_ANSI__)
       
    10 #define __PHYSFS_DOING_STRICT_ANSI__
       
    11 #endif
       
    12 
       
    13 /*
       
    14  * We cheat a little: I want the symlink version of stat() (lstat), and
       
    15  *  GCC/Linux will not declare it if compiled with the -ansi flag.
       
    16  *  If you are really lacking symlink support on your platform,
       
    17  *  you should #define __PHYSFS_NO_SYMLINKS__ before compiling this
       
    18  *  file. That will open a security hole, though, if you really DO have
       
    19  *  symlinks on your platform; it renders PHYSFS_permitSymbolicLinks(0)
       
    20  *  useless, since every symlink will be reported as a regular file/dir.
       
    21  */
       
    22 #if (defined __PHYSFS_DOING_STRICT_ANSI__)
       
    23 #undef __STRICT_ANSI__
       
    24 #endif
     9 #include <stdio.h>
    25 #include <stdio.h>
       
    26 #if (defined __PHYSFS_DOING_STRICT_ANSI__)
       
    27 #define __STRICT_ANSI__
       
    28 #endif
       
    29 
    10 #include <stdlib.h>
    30 #include <stdlib.h>
       
    31 #include <string.h>
       
    32 #include <ctype.h>
    11 #include <pthread.h>
    33 #include <pthread.h>
       
    34 #include <unistd.h>
       
    35 #include <sys/types.h>
       
    36 #include <pwd.h>
       
    37 #include <sys/stat.h>
       
    38 #include <dirent.h>
       
    39 #include <time.h>
       
    40 #include <errno.h>
       
    41 
    12 
    42 
    13 #define __PHYSICSFS_INTERNAL__
    43 #define __PHYSICSFS_INTERNAL__
    14 #include "physfs_internal.h"
    44 #include "physfs_internal.h"
    15 
    45 
    16 
    46 
    17 const char *__PHYSFS_platformDirSeparator = "/";
    47 const char *__PHYSFS_platformDirSeparator = "/";
    18 
    48 
    19 char **__PHYSFS_platformDetectAvailableCDs(void)
    49 char **__PHYSFS_platformDetectAvailableCDs(void)
    20 {
    50 {
       
    51     /* !!! write me. */
       
    52     char **retval = malloc(sizeof (char *));
       
    53     if (retval != NULL)
       
    54         *retval = NULL;
       
    55 
       
    56     return(retval);
    21 } /* __PHYSFS_detectAvailableCDs */
    57 } /* __PHYSFS_detectAvailableCDs */
    22 
    58 
    23 
    59 
    24 char *__PHYSFS_platformCalcBaseDir(char *argv0)
    60 char *__PHYSFS_platformCalcBaseDir(char *argv0)
    25 {
    61 {
    26     return(NULL);
    62     return(NULL);  /* default PhysicsFS behaviour is acceptable. */
    27 } /* __PHYSFS_platformCalcBaseDir */
    63 } /* __PHYSFS_platformCalcBaseDir */
    28 
    64 
    29 
    65 
       
    66 static char *copyEnvironmentVariable(const char *varname)
       
    67 {
       
    68     const char *envr = getenv(varname);
       
    69     char *retval = NULL;
       
    70 
       
    71     if (envr != NULL)
       
    72     {
       
    73         retval = malloc(strlen(envr) + 1);
       
    74         if (retval != NULL)
       
    75             strcpy(retval, envr);
       
    76     } /* if */
       
    77 
       
    78     return(retval);
       
    79 } /* copyEnvironmentVariable */
       
    80 
       
    81 
       
    82 static char *getUserNameByUID(void)
       
    83 {
       
    84     uid_t uid = getuid();
       
    85     struct passwd *pw;
       
    86     char *retval = NULL;
       
    87 
       
    88     pw = getpwuid(uid);
       
    89     if ((pw != NULL) && (pw->pw_name != NULL))
       
    90     {
       
    91         retval = malloc(strlen(pw->pw_name) + 1);
       
    92         if (retval != NULL)
       
    93             strcpy(retval, pw->pw_name);
       
    94     } /* if */
       
    95     
       
    96     return(retval);
       
    97 } /* getUserNameByUID */
       
    98 
       
    99 
       
   100 static char *getUserDirByUID(void)
       
   101 {
       
   102     uid_t uid = getuid();
       
   103     struct passwd *pw;
       
   104     char *retval = NULL;
       
   105 
       
   106     pw = getpwuid(uid);
       
   107     if ((pw != NULL) && (pw->pw_dir != NULL))
       
   108     {
       
   109         retval = malloc(strlen(pw->pw_dir) + 1);
       
   110         if (retval != NULL)
       
   111             strcpy(retval, pw->pw_dir);
       
   112     } /* if */
       
   113     
       
   114     return(retval);
       
   115 } /* getUserDirByUID */
       
   116 
       
   117 
    30 char *__PHYSFS_platformGetUserName(void)
   118 char *__PHYSFS_platformGetUserName(void)
    31 {
   119 {
       
   120     char *retval = getUserNameByUID();
       
   121     if (retval == NULL)
       
   122         retval = copyEnvironmentVariable("USER");
       
   123     return(retval);
    32 } /* __PHYSFS_platformGetUserName */
   124 } /* __PHYSFS_platformGetUserName */
    33 
   125 
    34 
   126 
    35 char *__PHYSFS_platformGetUserDir(void)
   127 char *__PHYSFS_platformGetUserDir(void)
    36 {
   128 {
       
   129     char *retval = copyEnvironmentVariable("HOME");
       
   130     if (retval == NULL)
       
   131         retval = getUserDirByUID();
       
   132     return(retval);
    37 } /* __PHYSFS_platformGetUserDir */
   133 } /* __PHYSFS_platformGetUserDir */
    38 
   134 
    39 
   135 
    40 int __PHYSFS_platformGetThreadID(void)
   136 int __PHYSFS_platformGetThreadID(void)
    41 {
   137 {
    42     return((int) pthread_self());
   138     return((int) pthread_self());
    43 } /* __PHYSFS_platformGetThreadID */
   139 } /* __PHYSFS_platformGetThreadID */
    44 
   140 
    45 
   141 
    46 int __PHYSFS_platformStricmp(const char *str1, const char *str2)
   142 /* -ansi and -pedantic flags prevent use of strcasecmp() on Linux. */
    47 {
   143 int __PHYSFS_platformStricmp(const char *x, const char *y)
    48     return(strcasecmp(str1, str2));
   144 {
       
   145     int ux, uy;
       
   146 
       
   147     do
       
   148     {
       
   149         ux = toupper((int) *x);
       
   150         uy = toupper((int) *y);
       
   151         if (ux > uy)
       
   152             return(1);
       
   153         else if (ux < uy)
       
   154             return(-1);
       
   155         x++;
       
   156         y++;
       
   157     } while ((ux) && (uy));
       
   158 
       
   159     return(0);
    49 } /* __PHYSFS_platformStricmp */
   160 } /* __PHYSFS_platformStricmp */
    50 
   161 
    51 
   162 
    52 int __PHYSFS_platformIsSymlink(const char *fname)
   163 int __PHYSFS_platformExists(const char *fname)
    53 {
   164 {
       
   165     struct stat statbuf;
       
   166     return(stat(fname, &statbuf) == 0);
       
   167 } /* __PHYSFS_platformExists */
       
   168 
       
   169 
       
   170 int __PHYSFS_platformIsSymLink(const char *fname)
       
   171 {
       
   172 #if (defined __PHYSFS_NO_SYMLINKS__)
       
   173     return(0);
       
   174 #else
       
   175 
       
   176     struct stat statbuf;
       
   177     int retval = 0;
       
   178 
       
   179     if (lstat(fname, &statbuf) == 0)
       
   180     {
       
   181         if (S_ISLNK(statbuf.st_mode))
       
   182             retval = 1;
       
   183     } /* if */
       
   184     
       
   185     return(retval);
       
   186 
       
   187 #endif
    54 } /* __PHYSFS_platformIsSymlink */
   188 } /* __PHYSFS_platformIsSymlink */
    55 
   189 
    56 
   190 
    57 int __PHYSFS_platformIsDirectory(const char *fname)
   191 int __PHYSFS_platformIsDirectory(const char *fname)
    58 {
   192 {
       
   193     struct stat statbuf;
       
   194     int retval = 0;
       
   195 
       
   196     if (stat(fname, &statbuf) == 0)
       
   197     {
       
   198         if (S_ISDIR(statbuf.st_mode))
       
   199             retval = 1;
       
   200     } /* if */
       
   201     
       
   202     return(retval);
    59 } /* __PHYSFS_platformIsDirectory */
   203 } /* __PHYSFS_platformIsDirectory */
    60 
   204 
    61 
   205 
       
   206 char *__PHYSFS_platformCvtToDependent(const char *prepend,
       
   207                                       const char *dirName,
       
   208                                       const char *append)
       
   209 {
       
   210     int len = ((prepend) ? strlen(prepend) : 0) +
       
   211               ((append) ? strlen(append) : 0) +
       
   212               strlen(dirName) + 1;
       
   213     char *retval = malloc(len);
       
   214 
       
   215     BAIL_IF_MACRO(retval == NULL, ERR_OUT_OF_MEMORY, NULL);
       
   216 
       
   217     /* platform-independent notation is Unix-style already.  :)  */
       
   218 
       
   219     if (prepend)
       
   220         strcpy(retval, prepend);
       
   221     else
       
   222         retval[0] = '\0';
       
   223 
       
   224     strcat(retval, dirName);
       
   225 
       
   226     if (append)
       
   227         strcat(retval, append);
       
   228 
       
   229     return(retval);
       
   230 } /* __PHYSFS_platformCvtToDependent */
       
   231 
       
   232 
       
   233 /* Much like my college days, try to sleep for 10 milliseconds at a time... */
       
   234 void __PHYSFS_platformTimeslice(void)
       
   235 {
       
   236     struct timespec napTime;
       
   237     napTime.tv_sec = 0;
       
   238     napTime.tv_nsec = 10 * 1000 * 1000;  /* specified in nanoseconds. */
       
   239     nanosleep(&napTime, NULL);           /* don't care if it fails. */
       
   240 } /* __PHYSFS_platformTimeslice */
       
   241 
       
   242 
       
   243 LinkedStringList *__PHYSFS_platformEnumerateFiles(const char *dirname)
       
   244 {
       
   245     LinkedStringList *retval = NULL;
       
   246     LinkedStringList *l = NULL;
       
   247     LinkedStringList *prev = NULL;
       
   248     DIR *dir;
       
   249     struct dirent *ent;
       
   250 
       
   251     errno = 0;
       
   252     dir = opendir(dirname);
       
   253     BAIL_IF_MACRO(dir == NULL, strerror(errno), NULL);
       
   254 
       
   255     while (1)
       
   256     {
       
   257         ent = readdir(dir);
       
   258         if (ent == NULL)   /* we're done. */
       
   259             break;
       
   260 
       
   261         l = (LinkedStringList *) malloc(sizeof (LinkedStringList));
       
   262         if (l != NULL)
       
   263             break;
       
   264 
       
   265         l->str = (char *) malloc(strlen(ent->d_name) + 1);
       
   266         if (l->str == NULL)
       
   267         {
       
   268             free(l);
       
   269             break;
       
   270         } /* if */
       
   271 
       
   272         if (retval == NULL)
       
   273             retval = l;
       
   274         else
       
   275             prev->next = l;
       
   276 
       
   277         prev = l;
       
   278         l->next = NULL;
       
   279     } /* while */
       
   280 
       
   281     closedir(dir);
       
   282     return(retval);
       
   283 } /* __PHYSFS_platformEnumerateFiles */
       
   284 
       
   285 
    62 /* end of unix.c ... */
   286 /* end of unix.c ... */
    63 
   287