LTP GCOV extension - code coverage report
Current view: directory - src/base - pdf-fsys-disk.c
Test: libgnupdf.info
Date: 2010-07-31 Instrumented lines: 364
Code covered: 42.0 % Executed lines: 153

       1                 : /* -*- mode: C -*-
       2                 :  *
       3                 :  *       File:         pdf-fsys-disk.c
       4                 :  *       Date:         Thu May 22 18:27:35 2008
       5                 :  *
       6                 :  *       GNU PDF Library - Disk Filesystem Implementation
       7                 :  *
       8                 :  */
       9                 : 
      10                 : /* Copyright (C) 2008 Free Software Foundation, Inc. */
      11                 : 
      12                 : /* This program is free software: you can redistribute it and/or modify
      13                 :  * it under the terms of the GNU General Public License as published by
      14                 :  * the Free Software Foundation, either version 3 of the License, or
      15                 :  * (at your option) any later version.
      16                 :  *
      17                 :  * This program is distributed in the hope that it will be useful,
      18                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      19                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20                 :  * GNU General Public License for more details.
      21                 :  *
      22                 :  * You should have received a copy of the GNU General Public License
      23                 :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24                 :  */
      25                 : 
      26                 : #include <config.h>
      27                 : 
      28                 : #include <errno.h>
      29                 : #include <stdio.h>
      30                 : #include <stdio-safer.h>
      31                 : #include <string.h>
      32                 : #include <sys/stat.h>
      33                 : 
      34                 : #if defined PDF_HOST_WIN32 || defined PDF_HOST_BSD
      35                 : #   include <sys/param.h>
      36                 : #   if defined PDF_HOST_BSD
      37                 : #      include <sys/mount.h>
      38                 : #   endif /* PDF_HOST_BSD */
      39                 : #else
      40                 : #   include <sys/statfs.h>
      41                 : #endif /* PDF_HOST_WIN32 | PDF_HOST_BSD */
      42                 : 
      43                 : #if defined PDF_HOST_WIN32
      44                 : #   include <windows.h>
      45                 : #   include <wchar.h>
      46                 : #endif /* !PDF_HOST_WIN32 */
      47                 : 
      48                 : #include <dirent.h>
      49                 : #include <unistd.h>
      50                 : 
      51                 : #include <pdf-types.h>
      52                 : #include <pdf-error.h>
      53                 : #include <pdf-fsys-disk.h>
      54                 : 
      55                 : /* Private function declarations */
      56                 : 
      57                 : static pdf_status_t
      58                 : __pdf_fsys_disk_get_status_from_errno(int _errno);
      59                 : static pdf_status_t
      60                 : __pdf_fsys_disk_get_host_path (const pdf_text_t path,
      61                 :                                pdf_char_t **host_path,
      62                 :                                pdf_size_t *host_path_size);
      63                 : static pdf_status_t
      64                 : __pdf_fsys_disk_set_host_path (const pdf_char_t *host_path,
      65                 :                                const pdf_size_t  host_path_size,
      66                 :                                pdf_text_t *p_path);
      67                 : static pdf_status_t
      68                 : __pdf_fsys_disk_is_writable_from_host_path(const pdf_char_t *host_path,
      69                 :                                            pdf_bool_t *p_result);
      70                 : static pdf_status_t
      71                 : __pdf_fsys_disk_is_readable_from_host_path(const pdf_char_t *host_path,
      72                 :                                            pdf_bool_t *p_result);
      73                 : static pdf_status_t
      74                 : __pdf_fsys_disk_file_get_size_from_host_path(const pdf_char_t *host_path,
      75                 :                                              pdf_size_t *p_result);
      76                 : static const pdf_char_t *
      77                 : __pdf_fsys_disk_get_mode_string(const enum pdf_fsys_file_mode_e mode);
      78                 : 
      79                 : #ifdef PDF_HOST_WIN32
      80                 : static pdf_bool_t
      81                 : __pdf_fsys_disk_win32_device_p (pdf_text_t path);
      82                 : #endif
      83                 : 
      84                 : /*
      85                 :  * Filesystem Interface Implementation
      86                 :  */
      87                 : 
      88                 : pdf_status_t
      89                 : pdf_fsys_disk_init (void **data)
      90               0 : {
      91                 :   /* Do nothing.  */
      92               0 :   *data = NULL;
      93               0 :   return PDF_OK;
      94                 : }
      95                 : 
      96                 : pdf_status_t
      97                 : pdf_fsys_disk_cleanup (void *data)
      98               0 : {
      99                 :   /* Do nothing.  */
     100               0 :   return PDF_OK;
     101                 : }
     102                 : 
     103                 : #ifdef PDF_HOST_WIN32
     104                 : 
     105                 : pdf_i64_t
     106                 : pdf_fsys_disk_get_free_space (void *data,
     107                 :                               pdf_text_t path_name)
     108                 : {
     109                 :   pdf_char_t *utf16le_path = NULL;
     110                 :   pdf_u32_t utf16le_path_size = 0;
     111                 :   ULARGE_INTEGER free_bytes;
     112                 :   pdf_i64_t result = pdf_i64_new((32 << 1),1); /* (-1) */
     113                 : 
     114                 :   /* Note that as we get the string as UTF-16LE with LAST NUL suffix,
     115                 :    *  it's equivalent to a wchar_t in windows environments */
     116                 : 
     117                 : 
     118                 :   if (pdf_text_get_unicode (&utf16le_path,
     119                 :                             &utf16le_path_size,
     120                 :                             path_name,
     121                 :                             PDF_TEXT_UTF16_LE,
     122                 :                             (PDF_TEXT_UNICODE_WITH_NUL_SUFFIX |     \
     123                 :                              PDF_TEXT_UNICODE_WITH_BOM)) != PDF_OK)
     124                 :     {
     125                 :       PDF_DEBUG_BASE("Couldn't get UTF-16LE path");
     126                 :     }
     127                 :   else
     128                 :     {
     129                 :       /* No need to get the drive letter of the specified path:
     130                 :        * This parameter does not have to specify the root directory on a disk.
     131                 :        *  The function accepts any directory on a disk.
     132                 :        **/
     133                 : 
     134                 : 
     135                 :       /* Get the information from the filesystem
     136                 :        *
     137                 :        * BOOL WINAPI GetDiskFreeSpaceEx(
     138                 :        *  __in_opt   LPCTSTR lpDirectoryName,
     139                 :        *  __out_opt  PULARGE_INTEGER lpFreeBytesAvailable,
     140                 :        *  __out_opt  PULARGE_INTEGER lpTotalNumberOfBytes,
     141                 :        *  __out_opt  PULARGE_INTEGER lpTotalNumberOfFreeBytes
     142                 :        * );
     143                 :        *
     144                 :        **/
     145                 :       if (GetDiskFreeSpaceExW ((LPCWSTR) utf16le_path,
     146                 :                                NULL, 
     147                 :                                NULL,
     148                 :                                &free_bytes))
     149                 :         {
     150                 :           pdf_status_t i64_ret_code;
     151                 :           /* Assign the number of bytes in the pdf_i64_t */
     152                 :           pdf_i64_assign(&result,
     153                 :                          free_bytes.HighPart,
     154                 :                          free_bytes.LowPart,
     155                 :                          &i64_ret_code);
     156                 :         }
     157                 : 
     158                 :       /* Cleanup */
     159                 :       pdf_dealloc (utf16le_path);
     160                 :     }
     161                 : 
     162                 :   /* Return the free space in octects */
     163                 :   return result;
     164                 : }
     165                 : 
     166                 : #else
     167                 : 
     168                 : pdf_i64_t
     169                 : pdf_fsys_disk_get_free_space (void *data,
     170                 :                               pdf_text_t path_name)
     171               2 : {
     172               2 :   pdf_i64_t result = pdf_i64_new((32 << 1),1); /* (-1) */
     173                 : 
     174                 :   /* Safety check that path_name is a valid pointer */
     175               2 :   if(path_name != NULL)
     176                 :     {
     177                 :       struct statfs fs_stats;
     178               2 :       pdf_char_t *host_path = NULL;
     179               2 :       pdf_size_t host_path_size = 0;
     180                 : 
     181                 : 
     182                 :       /* We get the string in HOST-encoding (with NUL-suffix) */
     183               2 :       if (__pdf_fsys_disk_get_host_path (path_name,
     184                 :                                        &host_path,
     185                 :                                        &host_path_size) != PDF_OK)
     186                 :         {
     187                 :           PDF_DEBUG_BASE("Couldn't get host-encoded path");
     188                 :         }
     189                 :       else
     190                 :         {
     191                 :           PDF_DEBUG_BASE("Getting free bytes of FS at path '%s'...", host_path);
     192               2 :           if (statfs ((const char *) host_path, &fs_stats) == 0)
     193                 :             {
     194               1 :               pdf_status_t i64_ret_code = PDF_OK;
     195                 :               /* Compute the number of bytes in the pdf_i64_t */
     196               1 :               pdf_i64_assign_quick(&result,
     197                 :                                    fs_stats.f_bfree,
     198                 :                                    &i64_ret_code);  
     199                 :               /* Only continue operation if assign is OK */
     200               1 :               if(i64_ret_code == PDF_OK)
     201                 :                 {
     202               1 :                   pdf_i64_mult_i32(&result,
     203                 :                                    result,
     204                 :                                    fs_stats.f_bsize,
     205                 :                                    &i64_ret_code);
     206                 :                 }
     207                 :               /* If any of the previous failed, reset return value */
     208               1 :               if(i64_ret_code != PDF_OK)
     209                 :                 {
     210                 :                   PDF_DEBUG_BASE("Couldn't compute bfree*bsize");
     211               0 :                   pdf_i64_assign_quick(&result, -1, &i64_ret_code); /* (-1) */
     212                 :                 }
     213                 :             }
     214                 :           else
     215                 :             {
     216                 :               PDF_DEBUG_BASE("Statfs failed... at path: '%s'", host_path);
     217                 :             }
     218                 : 
     219                 :           /* Cleanup */
     220               2 :           pdf_dealloc (host_path);
     221                 :         }
     222                 :     }
     223                 : 
     224                 :   /* Return the free space in octects */
     225               2 :   return result;
     226                 : }
     227                 : 
     228                 : #endif /* !PDF_HOST_WIN32 */
     229                 : 
     230                 : 
     231                 : 
     232                 : /* Private function to de-initialize and de-allocate base file data */
     233                 : static void
     234                 : __pdf_fsys_deinit_base_file_data(pdf_fsys_disk_file_t *p_file_data)
     235              25 : {
     236              25 :   if((p_file_data != NULL) && \
     237                 :      (*p_file_data != NULL))
     238                 :     {
     239              25 :       if((*p_file_data)->unicode_path != NULL)
     240                 :         {
     241              25 :           pdf_text_destroy ((*p_file_data)->unicode_path);
     242                 :         }
     243              25 :       if((*p_file_data)->host_path != NULL)
     244                 :         {
     245              25 :           pdf_dealloc((*p_file_data)->host_path);
     246                 :         }
     247              25 :       pdf_dealloc (*p_file_data);
     248              25 :       *p_file_data = NULL;
     249                 :     }
     250              25 : }
     251                 : 
     252                 : 
     253                 : /* Private function to allocate and initialize base file data */
     254                 : static pdf_fsys_disk_file_t
     255                 : __pdf_fsys_init_base_file_data(const pdf_text_t path_name)
     256              25 : {
     257              25 :   pdf_fsys_disk_file_t file_data = NULL;
     258              25 :   if(path_name != NULL)
     259                 :     {
     260                 :       /* Allocate private data storage for the file */
     261              25 :       file_data = (pdf_fsys_disk_file_t) pdf_alloc (sizeof(struct pdf_fsys_disk_file_s));
     262              25 :       if(file_data != NULL)
     263                 :         {
     264              25 :           memset(file_data, 0, sizeof(struct pdf_fsys_disk_file_s));
     265                 : 
     266                 :           /* Make and store a copy of the unicode file path and get the host
     267                 :              encoded path */
     268              25 :           file_data->unicode_path = pdf_text_dup (path_name);
     269              25 :           if(file_data->unicode_path != NULL)
     270                 :             {
     271              25 :               if (__pdf_fsys_disk_get_host_path(file_data->unicode_path,
     272                 :                                                 &(file_data->host_path),
     273                 :                                                 &(file_data->host_path_size)) != PDF_OK)
     274                 :                 {
     275               0 :                   pdf_text_destroy(file_data->unicode_path);
     276               0 :                   pdf_dealloc(file_data);
     277               0 :                   file_data = NULL;
     278                 :                 }
     279                 :             }
     280                 :           else
     281                 :             {
     282               0 :               pdf_dealloc(file_data);
     283               0 :               file_data = NULL;
     284                 :             }
     285                 :         }
     286                 :     }
     287              25 :   return file_data;
     288                 : }
     289                 : 
     290                 : 
     291                 : 
     292                 : /* Host-dependent fopen() */
     293                 : #ifdef PDF_HOST_WIN32
     294                 : #define PDF_FOPEN(f,m) _wfopen((wchar_t *)f,(wchar_t *)m)
     295                 : #else
     296                 : #define PDF_FOPEN(f,m) fopen_safer((char *)f,(char *)m)
     297                 : #endif
     298                 : 
     299                 : 
     300                 : pdf_status_t
     301                 : pdf_fsys_disk_file_open (void *data,
     302                 :                          const pdf_text_t path_name,
     303                 :                          const enum pdf_fsys_file_mode_e mode,
     304                 :                          pdf_fsys_file_t *p_file)
     305              24 : {
     306              24 :   pdf_status_t ret_status = PDF_EBADDATA;
     307                 : 
     308              24 :   if((path_name != NULL) && \
     309                 :      (p_file != NULL))
     310                 :     {
     311              24 :       pdf_fsys_file_t file = NULL;
     312              24 :       pdf_fsys_disk_file_t file_data = NULL;
     313                 :       const pdf_char_t * mode_str;
     314                 : 
     315                 :       /* Allocate file struct */
     316              24 :       file = (pdf_fsys_file_t)pdf_alloc(sizeof(struct pdf_fsys_file_s));
     317                 : 
     318              24 :       if(file != NULL)
     319                 :         {
     320                 :           /* Get base data */
     321              24 :           file_data = __pdf_fsys_init_base_file_data(path_name);
     322                 : 
     323                 :           /* Get the mode string for fopen */
     324              24 :           mode_str =__pdf_fsys_disk_get_mode_string(mode);
     325                 : 
     326                 :           /* Only continue if previous operations went ok */
     327              24 :           if((file_data != NULL) &&             \
     328                 :              (mode_str != NULL))
     329                 :             {
     330                 :               /* Open the file */
     331              24 :               file_data->file_descriptor = PDF_FOPEN(file_data->host_path, mode_str);
     332                 :               /* If got a good FD, set output data */
     333              24 :               if (file_data->file_descriptor != NULL)
     334                 :                 {
     335                 :                   /* Store the mode */
     336              22 :                   file_data->file_mode = mode;
     337                 :                   /* Store reference to the file data in the output variable*/
     338              22 :                   file->data = (void *) file_data;
     339                 :                   /* Set the filesystem for the file */
     340              22 :                   file->fs = NULL; /* This is the default filesystem */
     341                 : 
     342                 :                   /* Finally, if everything went ok, put output element */
     343              22 :                   *p_file = file;
     344                 : 
     345                 :                   /* All ok ! */
     346              22 :                   ret_status = PDF_OK;
     347                 :                 }
     348                 :               else
     349                 :                 {
     350                 :                   PDF_DEBUG_BASE("fopen failed...");
     351                 :                   /* Deallocate and deinit base file data */
     352               2 :                   __pdf_fsys_deinit_base_file_data(&file_data);
     353               2 :                   pdf_dealloc(file);
     354                 :                   /* Get pdf_status_t code from errno */
     355               2 :                   ret_status = __pdf_fsys_disk_get_status_from_errno(errno);
     356                 :                 }
     357                 :             }
     358                 :           else
     359                 :             {
     360               0 :               pdf_dealloc(file);
     361                 :             }
     362                 :         }
     363                 :     }
     364                 : 
     365                 :   /* All was ok */
     366              24 :   return ret_status;
     367                 : }
     368                 : 
     369                 : pdf_status_t
     370                 : pdf_fsys_disk_file_open_tmp (void *data,
     371                 :                              pdf_fsys_file_t *p_file)
     372               1 : {
     373                 :   pdf_text_t path_name;
     374               1 :   pdf_status_t ret_status = PDF_ERROR;
     375               1 :   pdf_fsys_file_t file = NULL;
     376               1 :   pdf_fsys_disk_file_t file_data = NULL;
     377                 :   
     378                 : 
     379               1 :   file = (pdf_fsys_file_t) pdf_alloc (sizeof (struct pdf_fsys_file_s));
     380               1 :   file->fs = NULL; /* Default filesystem.  */
     381                 :   
     382               1 :   if (file != NULL)
     383                 :     {
     384                 :       /* Create a dummy path name, so we can manage the temporary file
     385                 :          like an ordinary file.  */
     386               1 :       if (pdf_text_new_from_unicode ((pdf_char_t *) "tmp",
     387                 :                                      3,
     388                 :                                      PDF_TEXT_UTF8,
     389                 :                                      &path_name)
     390                 :           != PDF_OK)
     391                 :         {
     392               0 :           ret_status = PDF_ENOMEM;
     393                 :         }
     394                 :       else
     395                 :         {
     396                 :           /* Get base data.  */
     397               1 :           file_data = __pdf_fsys_init_base_file_data (path_name);
     398               1 :           file_data->file_mode = PDF_FSYS_OPEN_MODE_RW;
     399                 : 
     400                 :           /* Open a temporary file.  */
     401               1 :           file_data->file_descriptor = tmpfile_safer ();
     402               1 :           if (file_data->file_descriptor != NULL)
     403                 :             {
     404                 :               /* Success.  */
     405               1 :               file->data = (void *) file_data;
     406               1 :               *p_file = file;
     407               1 :               ret_status = PDF_OK;
     408                 :             }
     409                 :           else
     410                 :             {
     411               0 :               pdf_text_destroy (path_name);
     412                 :             }
     413                 :         }
     414                 :     }
     415                 : 
     416               1 :   return ret_status;
     417                 : }
     418                 : 
     419                 : 
     420                 : pdf_status_t
     421                 : pdf_fsys_disk_file_close (pdf_fsys_file_t file)
     422              23 : {
     423              23 :   pdf_status_t ret_code = PDF_EBADDATA;
     424              23 :   if((file != NULL) && \
     425                 :      (file->data != NULL))
     426                 :     {
     427              23 :       ret_code = PDF_OK;
     428                 :       /* Close the I/O stream only if already open */
     429              23 :       if(((pdf_fsys_disk_file_t)(file->data))->file_descriptor != NULL)
     430                 :         {
     431              23 :           if(fclose (((pdf_fsys_disk_file_t)(file->data))->file_descriptor) == EOF)
     432                 :             {
     433                 :               PDF_DEBUG_BASE("fclose returned an error");
     434                 :               /* An error was detected closing the I/O stream */
     435               0 :               ret_code = PDF_ERROR;
     436                 :             }
     437                 :           PDF_DEBUG_BASE("Closed");
     438                 :           /* Deallocate other internal contents */
     439              23 :           __pdf_fsys_deinit_base_file_data((pdf_fsys_disk_file_t *)&(file->data));
     440                 :         }
     441                 :       else
     442                 :         {
     443                 :           PDF_DEBUG_BASE("File is already closed");
     444                 :         }
     445                 : 
     446              23 :       if(file != NULL)
     447                 :         {
     448              23 :           pdf_dealloc(file);
     449                 :         }
     450                 :     }
     451              23 :   return ret_code;
     452                 : }
     453                 : 
     454                 : 
     455                 : 
     456                 : /* Host-dependent mkdir() */
     457                 : #ifdef PDF_HOST_WIN32
     458                 : #define PDF_MKDIR(f,m) _wmkdir((const wchar_t *)f)
     459                 : #else
     460                 : #define PDF_MKDIR(f,m) mkdir((const char *)f,m)
     461                 : #endif
     462                 : 
     463                 : pdf_status_t
     464                 : pdf_fsys_disk_create_folder (void *data,
     465                 :                              const pdf_text_t path_name)
     466               0 : {
     467               0 :   pdf_status_t ret_code = PDF_EBADDATA;
     468               0 :   if(path_name != NULL)
     469                 :     {
     470                 :       pdf_char_t *host_path;
     471                 :       pdf_size_t host_path_size;
     472                 : 
     473                 :       /* Default return code */
     474               0 :       ret_code = PDF_OK;
     475                 : 
     476                 :       /* Get a host-encoded version of the path name */
     477               0 :       if (__pdf_fsys_disk_get_host_path(path_name, 
     478                 :                                         &host_path, 
     479                 :                                         &host_path_size) != PDF_OK)
     480                 :         {
     481                 :           PDF_DEBUG_BASE("Couldn't get host path to create the folder");
     482               0 :           ret_code = PDF_ERROR;
     483                 :         }
     484                 :       else
     485                 :         {
     486                 :           /* Set the permissions of the new directory (posix-only):
     487                 :              rwxr_xr_x
     488                 :           */
     489                 :           /* Open the file */
     490               0 :           if (PDF_MKDIR(host_path,                     \
     491                 :                         (S_IRUSR | S_IWUSR | S_IXUSR | \
     492                 :                          S_IRGRP | S_IXGRP |           \
     493                 :                          S_IROTH | S_IXOTH)) != 0)
     494                 :             {
     495                 :               PDF_DEBUG_BASE("mkdir failed with errno '%d'", errno);
     496               0 :               ret_code = __pdf_fsys_disk_get_status_from_errno(errno);
     497                 :             }
     498                 :         }
     499                 :     }
     500                 : 
     501               0 :   return ret_code;
     502                 : }
     503                 : 
     504                 : /* Host-dependent opendir(), closedir() and friends*/
     505                 : #ifdef PDF_HOST_WIN32
     506                 : #define PDF_DIR          _WDIR
     507                 : #define pdf_dirent_s     _wdirent
     508                 : #define PDF_OPENDIR(f)   _wopendir((const wchar_t *)f)
     509                 : #define PDF_READDIR(ds)  _wreaddir((PDF_DIR *)ds)
     510                 : #define PDF_CLOSEDIR(ds) _wclosedir((PDF_DIR *)ds)
     511                 :     /* In mingw dir_entry->d_namlen is an array of FILENAME_MAX
     512                 :        octects long. The dir_entry->d_namlen contain the length of
     513                 :        the name stored in d_name */
     514                 : #define PDF_NAMELEN(de)  (de->d_namlen)
     515                 : #else
     516                 : #define PDF_DIR          DIR
     517                 : #define pdf_dirent_s     dirent
     518                 : #define PDF_OPENDIR(f)   opendir((const char *)f)
     519                 : #define PDF_READDIR(ds)  readdir((PDF_DIR *)ds)
     520                 : #define PDF_CLOSEDIR(ds) closedir((PDF_DIR *)ds)
     521                 :     /* In POSIX systems dir_entry->d_name is a NULL-terminated
     522                 :        string */
     523                 : #define PDF_NAMELEN(de)  (strlen(de->d_name))
     524                 : 
     525                 : #endif /* !PDF_HOST_WIN32 */
     526                 : 
     527                 : 
     528                 : pdf_status_t
     529                 : pdf_fsys_disk_get_folder_contents (void *data,
     530                 :                                    const pdf_text_t path_name,
     531                 :                                    pdf_list_t item_list)
     532               0 : {
     533               0 :   pdf_status_t ret_code = PDF_EBADDATA;
     534               0 :   if(path_name != NULL)
     535                 :     {
     536               0 :       PDF_DIR *dir_stream = NULL;
     537               0 :       pdf_char_t *host_path = NULL;
     538                 :       pdf_size_t host_path_size;
     539               0 :       pdf_text_t entry_text = NULL;
     540                 :       pdf_u32_t name_length;
     541                 :   
     542                 :       /* Default here is ok... */
     543               0 :       ret_code = PDF_OK;
     544                 : 
     545                 :       /* Get the pathname in the host encoding */
     546               0 :       if (__pdf_fsys_disk_get_host_path(path_name,
     547                 :                                         &host_path,
     548                 :                                         &host_path_size) != PDF_OK)
     549                 :         {
     550                 :           PDF_DEBUG_BASE("Couldn't get host path to get folder contents");
     551               0 :           ret_code = PDF_ERROR;
     552                 :         }
     553                 :       else
     554                 :         {
     555                 :           /* Open the directory stream */
     556               0 :           dir_stream = PDF_OPENDIR(host_path);
     557               0 :           if (dir_stream == NULL)
     558                 :             {
     559                 :               PDF_DEBUG_BASE("opendir failed with errno: '%d'",errno);
     560               0 :               ret_code = __pdf_fsys_disk_get_status_from_errno(errno);
     561                 :             }
     562                 :           else
     563                 :             {
     564               0 :               struct pdf_dirent_s *dir_entry = NULL;
     565                 :               /* Scan directory contents */
     566               0 :               while ((ret_code == PDF_OK) &&                            \
     567                 :                      (dir_stream != NULL) &&                            \
     568                 :                      (dir_entry = PDF_READDIR (dir_stream)) != NULL)
     569                 :                 {
     570                 :                   /* Note that dir_entry is statically allocated and can be
     571                 :                      rewritten by a subsequent call. Also, there is not need to
     572                 :                      free that structure */
     573                 :               
     574                 :                   /* Get the length of the entry name */
     575               0 :                   name_length = PDF_NAMELEN(dir_entry);
     576                 :               
     577                 :                   /* Create the text object containing the entry name */
     578               0 :                   if ((__pdf_fsys_disk_set_host_path((pdf_char_t *)(dir_entry->d_name),
     579                 :                                                      name_length,
     580                 :                                                      &entry_text) != PDF_OK) ||
     581                 :                       (pdf_list_add_last (item_list, 
     582                 :                                           (void *) entry_text, NULL) != PDF_OK))
     583                 :                     {
     584                 :                       /* Stop loop and report an error */
     585               0 :                       ret_code = PDF_ERROR;
     586                 :                     }
     587                 :                 }
     588                 :               /* Close dir... */
     589               0 :               PDF_CLOSEDIR(dir_stream);
     590                 :             }
     591                 :         }
     592                 :     }
     593               0 :   return ret_code;
     594                 : }
     595                 : 
     596                 : 
     597                 : pdf_status_t
     598                 : pdf_fsys_disk_get_parent (void *data,
     599                 :                           const pdf_text_t path_name,
     600                 :                           pdf_text_t parent_path)
     601               0 : {
     602               0 :   pdf_status_t ret_code = PDF_EBADDATA;
     603               0 :   if((path_name != NULL) &&                     \
     604                 :      (parent_path != NULL))
     605                 :     {
     606                 :       /* TODO: This involves getting an absolute path from a relative path */
     607                 :     }
     608                 : 
     609               0 :   return ret_code;
     610                 : }
     611                 : 
     612                 : 
     613                 : /* Host-dependent rmdir() */
     614                 : #ifdef PDF_HOST_WIN32
     615                 : #define PDF_RMDIR(f) _wrmdir((wchar_t *)f)
     616                 : #else
     617                 : #define PDF_RMDIR(f) rmdir((char *)f)
     618                 : #endif
     619                 : 
     620                 : pdf_status_t
     621                 : pdf_fsys_disk_remove_folder (void *data,
     622                 :                              const pdf_text_t path_name)
     623               0 : {
     624               0 :   pdf_status_t ret_code = PDF_EBADDATA;
     625               0 :   if(path_name != NULL)
     626                 :     {
     627                 :       pdf_char_t *host_path;
     628                 :       pdf_size_t host_path_size;
     629                 : 
     630                 :       /* Get the pathname in the host encoding */
     631               0 :       if (__pdf_fsys_disk_get_host_path (path_name,
     632                 :                                          &host_path,
     633                 :                                          &host_path_size) != PDF_OK)
     634                 :         {
     635               0 :           ret_code = PDF_ERROR;
     636                 :         }
     637                 :       else
     638                 :         {
     639                 :           /* Try to remove the directory */
     640               0 :           if (PDF_RMDIR(host_path) != 0)
     641                 :             {
     642                 :               /* Cleanup */
     643               0 :               pdf_dealloc (host_path);
     644                 :               
     645               0 :               ret_code = __pdf_fsys_disk_get_status_from_errno(errno);
     646                 :             }
     647                 :         }
     648                 :       /* Cleanup */
     649               0 :       pdf_dealloc (host_path);
     650                 :     }
     651                 : 
     652               0 :   return ret_code;
     653                 : }
     654                 : 
     655                 : /* Host-dependent access() */
     656                 : #ifdef PDF_HOST_WIN32
     657                 : #define PDF_ACCESS(f,m) _waccess((wchar_t *)f,m)
     658                 : #else
     659                 : #define PDF_ACCESS(f,m) access((char *)f,m)
     660                 : #endif
     661                 : 
     662                 : 
     663                 : static pdf_status_t
     664                 : __pdf_fsys_disk_is_readable_from_host_path(const pdf_char_t *host_path,
     665                 :                                            pdf_bool_t *p_result)
     666               0 : {
     667               0 :   pdf_status_t ret_code = PDF_EBADDATA;
     668                 :   /* Check if file can be read */
     669               0 :   if((host_path != NULL) && \
     670                 :      (p_result != NULL))
     671                 :     {
     672               0 :       if(PDF_ACCESS(host_path, R_OK) == -1)
     673                 :         {
     674                 :           /* Now, either is not readable, or another error happened */
     675               0 :           if(errno == EACCES)
     676                 :             {
     677               0 :               *p_result = PDF_FALSE;
     678               0 :               ret_code = PDF_OK;
     679                 :             }
     680                 :           else
     681                 :             {
     682               0 :               ret_code = __pdf_fsys_disk_get_status_from_errno(errno);
     683                 :             }
     684                 :         }
     685                 :       else
     686                 :         {
     687               0 :           *p_result = PDF_TRUE;
     688               0 :           ret_code = PDF_OK;
     689                 :         }
     690                 :     }
     691               0 :   return ret_code;
     692                 : }
     693                 : 
     694                 : static pdf_status_t
     695                 : __pdf_fsys_disk_is_writable_from_host_path(const pdf_char_t *host_path,
     696                 :                                            pdf_bool_t *p_result)
     697               0 : {
     698               0 :   pdf_status_t ret_code = PDF_EBADDATA;
     699                 :   /* Check if file can be written */
     700               0 :   if((host_path != NULL)  && \
     701                 :      (p_result != NULL))
     702                 :     {
     703               0 :       if(PDF_ACCESS(host_path, W_OK) == -1)
     704                 :         {
     705                 :           /* Now, either is not readable, or another error happened */
     706               0 :           if(errno == EACCES)
     707                 :             {
     708               0 :               *p_result = PDF_FALSE;
     709               0 :               ret_code = PDF_OK;
     710                 :             }
     711                 :           else
     712                 :             {
     713               0 :               ret_code = __pdf_fsys_disk_get_status_from_errno(errno);
     714                 :             }
     715                 :         }
     716                 :       else
     717                 :         {
     718               0 :           *p_result = PDF_TRUE;
     719               0 :           ret_code = PDF_OK;
     720                 :         }
     721                 :     }
     722               0 :   return ret_code;
     723                 : }
     724                 : 
     725                 : /* Host-dependent stat() */
     726                 : #ifdef PDF_HOST_WIN32
     727                 : #define PDF_STAT(f,s) _wstat((wchar_t *)f,s)
     728                 : typedef struct _stat pdf_stat_s;
     729                 : #else
     730                 : #define PDF_STAT(f,s) stat((char *)f,s)
     731                 : typedef struct stat pdf_stat_s;
     732                 : #endif
     733                 : 
     734                 : static pdf_status_t
     735                 : __pdf_fsys_disk_file_get_size_from_host_path(const pdf_char_t *host_path,
     736                 :                                              pdf_size_t *p_result)
     737               3 : {
     738               3 :   pdf_status_t ret_code = PDF_EBADDATA;
     739                 :   /* Check if file can be written */
     740               3 :   if((host_path != NULL)  && \
     741                 :      (p_result != NULL))
     742                 :     {
     743                 : 
     744                 :       /* TODO:
     745                 :        * If available, we should try to use the 64-bit versions of stat() */
     746                 : 
     747                 :       pdf_stat_s file_info;
     748               6 :       if (PDF_STAT(host_path, &file_info) != 0)
     749                 :         {
     750               0 :           ret_code = __pdf_fsys_disk_get_status_from_errno(errno);
     751                 :         }
     752                 :       else
     753                 :         {
     754               3 :           *p_result = file_info.st_size;
     755               3 :           ret_code = PDF_OK;
     756                 :         }
     757                 :     }
     758                 : 
     759               3 :   return ret_code;
     760                 : }
     761                 : 
     762                 : 
     763                 : 
     764                 : pdf_status_t
     765                 : pdf_fsys_disk_get_item_props (void *data,
     766                 :                               pdf_text_t path_name,
     767                 :                               struct pdf_fsys_item_props_s *item_props)
     768               0 : {
     769               0 :   pdf_char_t* host_path = NULL;
     770               0 :   pdf_size_t host_path_len = 0;
     771               0 :   pdf_status_t ret_code = PDF_EBADDATA;
     772                 : 
     773                 :   /* Get host path */
     774               0 :   if((path_name != NULL) && \
     775                 :      (item_props != NULL))
     776                 :     {
     777               0 :       ret_code = __pdf_fsys_disk_get_host_path (path_name,
     778                 :                                                 &host_path,
     779                 :                                                 &host_path_len);
     780                 :     }
     781                 : 
     782                 :   /* Is readable ? */
     783               0 :   if(ret_code == PDF_OK)
     784                 :     {
     785               0 :       ret_code = __pdf_fsys_disk_is_readable_from_host_path(host_path,                 \
     786                 :                                                             &(item_props->is_readable));
     787                 :     }
     788                 : 
     789                 :   /* Is writable ? */
     790               0 :   if(ret_code == PDF_OK)
     791                 :     {
     792               0 :       ret_code = __pdf_fsys_disk_is_writable_from_host_path(host_path,                 \
     793                 :                                                             &(item_props->is_writable));
     794                 :     }
     795                 : 
     796                 :   /* TODO: is hidden ? */
     797                 : 
     798                 : 
     799                 :   /* TODO: Get creation date */
     800                 : 
     801                 : 
     802                 :   /* TODO: Get modification date */
     803                 : 
     804                 : 
     805                 :   /* Get file size */
     806               0 :   if(ret_code == PDF_OK)
     807                 :     {
     808                 :       pdf_size_t size;
     809                 : 
     810               0 :       ret_code = __pdf_fsys_disk_file_get_size_from_host_path(host_path, &size);
     811               0 :       if(ret_code == PDF_OK)
     812                 :         {
     813               0 :           item_props->file_size_high = 0;
     814               0 :           item_props->file_size_low = size;
     815                 :         }
     816                 :     }
     817                 : 
     818                 : 
     819                 :   /* TODO: Get folder size */
     820                 : 
     821                 : 
     822                 :   /* Clean aux host path */
     823               0 :   if (host_path != NULL)
     824                 :     {
     825               0 :       pdf_dealloc (host_path);
     826                 :     }
     827                 : 
     828               0 :   return ret_code;
     829                 : }
     830                 : 
     831                 : 
     832                 : pdf_bool_t
     833                 : pdf_fsys_disk_item_p (void *data,
     834                 :                       pdf_text_t path_name)
     835               0 : {
     836                 :   struct pdf_fsys_item_props_s item_props;
     837                 : #ifdef PDF_HOST_WIN32
     838                 :   if (__pdf_fsys_disk_win32_device_p(path_name) == PDF_TRUE)
     839                 :     {
     840                 :       return PDF_TRUE;
     841                 :     }
     842                 : #endif
     843               0 :   return ((pdf_fsys_disk_get_item_props(data,
     844                 :                                         path_name,
     845                 :                                         &item_props) == PDF_OK) ?
     846                 :           PDF_TRUE :
     847                 :           PDF_FALSE);
     848                 : }
     849                 : 
     850                 : 
     851                 : pdf_bool_t 
     852                 : pdf_fsys_disk_item_readable_p (void *data,
     853                 :                                pdf_text_t path_name)
     854               0 : {
     855               0 :   pdf_bool_t result = PDF_FALSE;
     856               0 :   if(path_name != NULL)
     857                 :     {
     858               0 :       pdf_char_t* host_path = NULL;
     859               0 :       pdf_size_t host_path_len = 0;
     860                 : 
     861               0 :       if(__pdf_fsys_disk_get_host_path (path_name,
     862                 :                                         &host_path,
     863                 :                                         &host_path_len) == PDF_OK)
     864                 :         {
     865               0 :           __pdf_fsys_disk_is_readable_from_host_path(host_path, &result);
     866               0 :           pdf_dealloc(host_path);
     867                 :         }
     868                 :     }
     869               0 :   return result;
     870                 : }
     871                 : 
     872                 : 
     873                 : 
     874                 : 
     875                 : pdf_bool_t
     876                 : pdf_fsys_disk_item_writable_p (void *data,
     877                 :                                pdf_text_t path_name)
     878               0 : {
     879               0 :   pdf_bool_t result = PDF_FALSE;
     880               0 :   if(path_name != NULL)
     881                 :     {
     882               0 :       pdf_char_t* host_path = NULL;
     883               0 :       pdf_size_t host_path_len = 0;
     884                 : 
     885               0 :       if(__pdf_fsys_disk_get_host_path (path_name,
     886                 :                                         &host_path,
     887                 :                                         &host_path_len) == PDF_OK)
     888                 :         {
     889               0 :           __pdf_fsys_disk_is_writable_from_host_path(host_path, &result);
     890               0 :           pdf_dealloc(host_path);
     891                 :         }
     892                 :     }
     893               0 :   return result;
     894                 : }
     895                 : 
     896                 : pdf_status_t
     897                 : pdf_fsys_disk_build_path (void *data,
     898                 :                           pdf_text_t * output,
     899                 :                           pdf_text_t first_element,
     900                 :                           pdf_list_t rest)
     901               1 : {
     902                 :   pdf_list_iterator_t itr;
     903                 :   pdf_text_t next, text_sep;
     904                 :   pdf_status_t st, st2;
     905                 : 
     906               2 :   st = pdf_list_iterator (rest, &itr);
     907               1 :   if (st != PDF_OK)
     908                 :     {
     909               0 :       return st;
     910                 :     }
     911                 : 
     912               1 :   *output = pdf_text_dup (first_element);
     913               1 :   if (*output == NULL)
     914                 :     {
     915                 :       pdf_list_iterator_free (&itr);
     916               0 :       return PDF_ENOMEM;
     917                 :     }
     918                 : 
     919                 : #if FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR
     920                 :   st = pdf_text_new_from_unicode ((pdf_char_t*)"\\",1,PDF_TEXT_UTF8, &text_sep);
     921                 : #else
     922               1 :   st = pdf_text_new_from_unicode ((pdf_char_t*)"/",1,PDF_TEXT_UTF8, &text_sep);
     923                 : #endif /* FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR */
     924                 : 
     925               1 :   if (st != PDF_OK)
     926                 :     {
     927                 :       pdf_list_iterator_free (&itr);
     928               0 :       pdf_text_destroy(*output);
     929               0 :       return st;
     930                 :     }
     931                 : 
     932                 :   /* Concatenate separator and next text object */
     933               2 :   st = pdf_list_iterator_next (&itr, (const void **) &next, NULL);
     934               4 :   while (st == PDF_OK)
     935                 :     {
     936               2 :       st2 = pdf_text_concat (*output, text_sep, PDF_TRUE);
     937               2 :       if (st2 != PDF_OK)
     938                 :         {
     939                 :           pdf_list_iterator_free (&itr);
     940               0 :           pdf_text_destroy(*output);
     941               0 :           pdf_text_destroy (text_sep);
     942               0 :           return st2;
     943                 :         }
     944                 :       
     945               2 :       st2 = pdf_text_concat (*output, next, PDF_TRUE);
     946               2 :       if (st2 != PDF_OK)
     947                 :         {
     948                 :           pdf_list_iterator_free (&itr);
     949               0 :           pdf_text_destroy(*output);
     950               0 :           pdf_text_destroy (text_sep);
     951               0 :           return st2;
     952                 :         }
     953               4 :       st = pdf_list_iterator_next (&itr, (const void **) &next, NULL);
     954                 :     }
     955                 : 
     956                 :   pdf_list_iterator_free (&itr);
     957               1 :   pdf_text_destroy (text_sep);
     958               1 :   return PDF_OK;
     959                 : }
     960                 : 
     961                 : 
     962                 : /*
     963                 :  * File Interface Implementation
     964                 :  */
     965                 : 
     966                 : enum pdf_fsys_file_mode_e
     967                 : pdf_fsys_disk_file_get_mode (pdf_fsys_file_t file)
     968               0 : {
     969               0 :   return (((file != NULL) && (file->data != NULL)) ?        \
     970                 :           (((pdf_fsys_disk_file_t)file->data)->file_mode) : \
     971                 :           PDF_FSYS_OPEN_MODE_INVALID);
     972                 : }
     973                 : 
     974                 : pdf_text_t 
     975                 : pdf_fsys_disk_file_get_url (pdf_fsys_file_t file)
     976               0 : {
     977               0 :   if((file != NULL) && (file->data != NULL))
     978                 :     {
     979                 : #ifdef PDF_HOST_WIN32
     980                 :       /* In W32, we just copy the path string */
     981                 :       return pdf_text_dup((((pdf_fsys_disk_file_t)file->data)->unicode_path));
     982                 : #else
     983                 :       /* In POSIX, we return file:/ plus the path string */ 
     984               0 :       pdf_text_t url = NULL;
     985                 : #define PDF_DISK_URL_PREFIX  (pdf_char_t *)"file:/"
     986               0 :       if(pdf_text_new_from_unicode(PDF_DISK_URL_PREFIX,
     987                 :                                    strlen((char *) PDF_DISK_URL_PREFIX),
     988                 :                                    PDF_TEXT_UTF8,
     989                 :                                    &url) == PDF_OK)
     990                 :         {
     991               0 :           if(pdf_text_concat(url,
     992                 :                              (((pdf_fsys_disk_file_t)file->data)->unicode_path),
     993                 :                              PDF_TRUE) == PDF_OK)
     994                 :             {
     995               0 :               return url;
     996                 :             }
     997                 :         }
     998                 : #undef PDF_DISK_URL_PREFIX
     999               0 :       if(url != NULL)
    1000                 :         {
    1001               0 :           pdf_text_destroy(url);
    1002                 :         }
    1003               0 :       return NULL;
    1004                 : #endif
    1005                 :     }
    1006                 :   else
    1007               0 :     return NULL;
    1008                 : }
    1009                 : 
    1010                 : pdf_status_t
    1011                 : pdf_fsys_disk_file_set_mode (pdf_fsys_file_t file,
    1012                 :                              enum pdf_fsys_file_mode_e new_mode)
    1013               0 : {
    1014               0 :   pdf_status_t ret_code = PDF_EBADDATA;
    1015               0 :   if(file != NULL)
    1016                 :     {
    1017               0 :       if(file->data == NULL)
    1018                 :         {
    1019               0 :           ret_code = PDF_ECLOSED;
    1020                 :         }
    1021                 :       else
    1022                 :         {
    1023               0 :           pdf_fsys_disk_file_t file_data = (pdf_fsys_disk_file_t)file->data;
    1024                 :           /* If modes are different, call reopen */
    1025               0 :           if(file_data->file_mode != new_mode)
    1026                 :             {
    1027               0 :               ret_code = pdf_fsys_disk_file_reopen(file,new_mode);
    1028                 :             }
    1029                 :           else
    1030                 :             {
    1031                 :               /* Same mode, so don't do anything */
    1032               0 :               ret_code = PDF_OK;
    1033                 :             }
    1034                 :         }
    1035                 :     }
    1036               0 :   return ret_code;
    1037                 : }
    1038                 : 
    1039                 : pdf_bool_t
    1040                 : pdf_fsys_disk_file_same_p (pdf_fsys_file_t file,
    1041                 :                            pdf_text_t path)
    1042               0 : {
    1043                 :   pdf_status_t stat;
    1044                 :   pdf_i32_t ret;
    1045                 :   pdf_bool_t case_sensitive;
    1046               0 :   pdf_fsys_disk_file_t work_file = (pdf_fsys_disk_file_t)file->data;
    1047                 : 
    1048                 : 
    1049                 : 
    1050                 :   /* TODO: Mac OS X should have a method in CoreFoundation libs to
    1051                 :    *  check if a the HFS+ filesystem is case-sensitive or not */
    1052                 : 
    1053                 : 
    1054                 :   /* Unix-like systems have case sensitive paths, Windows doesn't. */
    1055                 : #ifndef PDF_HOST_WIN32
    1056               0 :   case_sensitive = PDF_TRUE;
    1057                 : #else
    1058                 :   case_sensitive = PDF_FALSE;
    1059                 : #endif
    1060                 : 
    1061                 : 
    1062                 :   /* TODO : We should be able to get the whole ABSOLUTE path of the
    1063                 :    *         files, before comparing the routes */
    1064                 : 
    1065                 : 
    1066                 : 
    1067                 :   /* Compare text strings */
    1068               0 :   ret = pdf_text_cmp(work_file->unicode_path, path, case_sensitive, &stat);
    1069                 : 
    1070               0 :   return (((ret == 0 ) && (stat == PDF_OK)) ? PDF_TRUE : PDF_FALSE);
    1071                 : }
    1072                 : 
    1073                 : 
    1074                 : pdf_status_t
    1075                 : pdf_fsys_disk_file_get_pos (pdf_fsys_file_t file,
    1076                 :                             pdf_size_t *pos)
    1077              24 : {
    1078              24 :   if((file != NULL) && \
    1079                 :      (pos != NULL))
    1080                 :     {
    1081                 :       long cpos;
    1082              24 :       cpos = ftell (((pdf_fsys_disk_file_t)file->data)->file_descriptor);
    1083              24 :       if (cpos<0)
    1084                 :         {
    1085               0 :           return __pdf_fsys_disk_get_status_from_errno (errno);
    1086                 :         }
    1087                 :       else
    1088                 :         {
    1089              24 :           *pos = cpos;
    1090              24 :           return PDF_OK;
    1091                 :         }
    1092                 :     }
    1093                 :   else
    1094                 :     {
    1095               0 :       return PDF_EBADDATA;
    1096                 :     }
    1097                 : }
    1098                 : 
    1099                 : pdf_status_t
    1100                 : pdf_fsys_disk_file_set_pos (pdf_fsys_file_t file,
    1101                 :                             pdf_size_t new_pos)
    1102              48 : {
    1103              48 :   if(file != NULL)
    1104                 :     {
    1105                 :       int st;
    1106              96 :       st = fseek (((pdf_fsys_disk_file_t)file->data)->file_descriptor,
    1107                 :                  new_pos, SEEK_SET);
    1108              48 :       if (st < 0)
    1109                 :         {
    1110               0 :           return __pdf_fsys_disk_get_status_from_errno (errno);
    1111                 :         }
    1112                 :       else
    1113                 :         {
    1114              48 :           return PDF_OK;
    1115                 :         }
    1116                 :     }
    1117                 :   else
    1118                 :     {
    1119               0 :       return PDF_EBADDATA;
    1120                 :     }
    1121                 : }
    1122                 : 
    1123                 : pdf_bool_t
    1124                 : pdf_fsys_disk_file_can_set_size_p (pdf_fsys_file_t file,
    1125                 :                                    pdf_size_t size)
    1126               0 : {
    1127                 :   /* FIXME: Please implement me XD */
    1128               0 :   return PDF_TRUE;
    1129                 : }
    1130                 : 
    1131                 : pdf_size_t
    1132                 : pdf_fsys_disk_file_get_size (pdf_fsys_file_t file)
    1133               3 : {
    1134                 :   pdf_size_t size;
    1135               3 :   if(__pdf_fsys_disk_file_get_size_from_host_path(((pdf_fsys_disk_file_t)file->data)->host_path,
    1136                 :                                                   &size) == PDF_OK)
    1137                 :     {
    1138               3 :       return size;
    1139                 :     }
    1140                 :   else
    1141                 :     {
    1142                 :       /* Should we change the API to return pdf_status_t ? */
    1143               0 :       return 0;
    1144                 :     }
    1145                 : }
    1146                 : 
    1147                 : pdf_status_t
    1148                 : pdf_fsys_disk_file_set_size (pdf_fsys_file_t file,
    1149                 :                              pdf_size_t size)
    1150               0 : {
    1151                 :   /* FIXME: Please implement me :D */
    1152               0 :   return PDF_OK;
    1153                 : }
    1154                 : 
    1155                 : 
    1156                 : pdf_status_t
    1157                 : pdf_fsys_disk_file_read (pdf_fsys_file_t file, pdf_char_t *buf,
    1158                 :                          pdf_size_t bytes, pdf_size_t *read_bytes)
    1159              24 : {
    1160              24 :   pdf_status_t ret = PDF_EBADDATA;
    1161              24 :   if((file != NULL) &&                          \
    1162                 :      (buf != NULL))
    1163                 :     {
    1164              24 :       pdf_fsys_disk_file_t file_data = NULL;
    1165              24 :       file_data = (pdf_fsys_disk_file_t)(file->data);
    1166                 : 
    1167                 :       /* Check if the file is open. */
    1168              24 :       if(file_data == NULL)
    1169                 :         {
    1170                 :           PDF_DEBUG_BASE("File is closed! Can't read data");
    1171                 :         }
    1172                 :       else
    1173                 :         {
    1174              24 :           *read_bytes = fread(buf,
    1175                 :                               1,
    1176                 :                               bytes,
    1177                 :                               file_data->file_descriptor);
    1178              24 :           if (feof(file_data->file_descriptor))
    1179                 :             {
    1180              22 :               ret = PDF_EEOF;
    1181                 :             }
    1182               2 :           else if (ferror(file_data->file_descriptor))
    1183                 :             {
    1184               0 :               ret = PDF_ERROR;
    1185                 :             }
    1186                 :           else
    1187                 :             {
    1188               2 :               ret = PDF_OK;
    1189                 :             }
    1190                 :         }
    1191                 :     }
    1192                 :   else
    1193                 :     {
    1194                 :       PDF_DEBUG_BASE("Invalid inputs to file_read! (file:%p, buf:%p, size:%u)",
    1195                 :                      file,buf,bytes);
    1196                 :     }
    1197              24 :   return ret;
    1198                 : }
    1199                 : 
    1200                 : 
    1201                 : pdf_status_t
    1202                 : pdf_fsys_disk_file_write (pdf_fsys_file_t file, pdf_char_t *buf,
    1203                 :                           pdf_size_t bytes, pdf_size_t *written_bytes)
    1204               9 : {
    1205               9 :   pdf_status_t ret = PDF_EBADDATA;
    1206               9 :   if((file != NULL) && \
    1207                 :      (buf != NULL))
    1208                 :     {
    1209               9 :       pdf_fsys_disk_file_t file_data = NULL;
    1210               9 :       file_data = (pdf_fsys_disk_file_t)(file->data);
    1211                 : 
    1212                 :       /* Check if the file is open. */
    1213               9 :       if(file_data == NULL)
    1214                 :         {
    1215                 :           PDF_DEBUG_BASE("File is closed! Can't write data");
    1216                 :         }
    1217                 :       else
    1218                 :         {
    1219               9 :           *written_bytes = fwrite(buf,
    1220                 :                                   1,
    1221                 :                                   bytes,
    1222                 :                                   file_data->file_descriptor);
    1223               9 :           if (ferror(file_data->file_descriptor))
    1224                 :             {
    1225               0 :               if (errno == ENOSPC)
    1226                 :                 {
    1227               0 :                   ret = PDF_ENOMEM;
    1228                 :                 }
    1229                 :               else
    1230                 :                 {
    1231               0 :                   ret = PDF_ERROR;
    1232                 :                 }
    1233                 :             }
    1234                 :           else
    1235                 :             {
    1236               9 :               ret = PDF_OK;
    1237                 :             }
    1238                 :         }
    1239                 :     }
    1240                 :   else
    1241                 :     {
    1242                 :       PDF_DEBUG_BASE("Invalid inputs to file_write! (file:%p, buf:%p, size:%u)",
    1243                 :                      file,buf,bytes);
    1244                 :     }
    1245               9 :   return ret;
    1246                 : 
    1247                 : }
    1248                 : 
    1249                 : 
    1250                 : pdf_status_t
    1251                 : pdf_fsys_disk_file_flush (pdf_fsys_file_t file)
    1252               0 : {
    1253                 :   pdf_fsys_disk_file_t file_data;
    1254                 :   pdf_status_t ret_code;
    1255                 : 
    1256               0 :   file_data = (pdf_fsys_disk_file_t) file->data;
    1257                 : 
    1258               0 :   if (fflush (file_data->file_descriptor) != 0)
    1259                 :     {
    1260                 :       /* On Windows platforms (excluding Cygwin), fflush does not
    1261                 :          set errno upon failure. */
    1262                 : #ifndef PDF_HOST_WIN32
    1263               0 :       ret_code = __pdf_fsys_disk_get_status_from_errno(errno);
    1264                 : #else
    1265                 :       ret_code = PDF_ERROR;
    1266                 : #endif
    1267                 :     }
    1268                 :   else
    1269                 :     {
    1270               0 :       ret_code = PDF_OK;
    1271                 :     }
    1272                 : 
    1273               0 :   return ret_code;
    1274                 : }
    1275                 : 
    1276                 : 
    1277                 : pdf_status_t
    1278                 : pdf_fsys_disk_file_request_ria (pdf_fsys_file_t file,
    1279                 :                                 pdf_size_t offset,
    1280                 :                                 pdf_size_t count)
    1281               0 : {
    1282                 :   /* This filesystem implementation do not provide Read-In-Advance
    1283                 :    * capabilities, so this function is a no-op */
    1284                 : 
    1285               0 :   return PDF_OK;
    1286                 : }
    1287                 : 
    1288                 : pdf_bool_t
    1289                 : pdf_fsys_disk_file_has_ria (pdf_fsys_file_t file)
    1290               0 : {
    1291                 :   /* This filesystem implementation do not provide Read-In-Advance
    1292                 :    * capabilities */
    1293                 : 
    1294               0 :   return PDF_FALSE;
    1295                 : }
    1296                 : 
    1297                 : pdf_status_t
    1298                 : pdf_fsys_disk_file_cancel_ria (pdf_fsys_file_t file)
    1299               0 : {
    1300                 :   /* This filesystem implementation do not provide Read-In-Advance
    1301                 :    * capabilities, so this function is a no-op */
    1302                 : 
    1303               0 :   return PDF_OK;
    1304                 : }
    1305                 : 
    1306                 : 
    1307                 : /* Host-dependent freopen() */
    1308                 : #ifdef PDF_HOST_WIN32
    1309                 : #define PDF_FREOPEN(f,m,s) _wfreopen((wchar_t *)f,(wchar_t *)m,s)
    1310                 : #else
    1311                 : #define PDF_FREOPEN(f,m,s) freopen_safer ((char *)f,(char *)m,s)
    1312                 : #endif
    1313                 : 
    1314                 : 
    1315                 : pdf_status_t
    1316                 : pdf_fsys_disk_file_reopen (pdf_fsys_file_t file,
    1317                 :                            enum pdf_fsys_file_mode_e mode)
    1318               0 : {
    1319               0 :   pdf_status_t ret_code = PDF_EBADDATA;
    1320               0 :   if(file != NULL)
    1321                 :     {
    1322               0 :       pdf_fsys_disk_file_t file_data = NULL;
    1323                 : 
    1324               0 :       file_data = (pdf_fsys_disk_file_t)(file->data);
    1325                 : 
    1326                 :       /* Check if the file is open. If it's closed, error must be returned
    1327                 :        *  as reopen doesn't have the file path input */
    1328                 :       /* Check if file is closed (no valid data in object */
    1329               0 :       if(file_data == NULL)
    1330                 :         {
    1331                 :           PDF_DEBUG_BASE("File is closed! Can't re-open");
    1332               0 :           ret_code = PDF_ECLOSED;
    1333                 :         }
    1334               0 :       else if(file_data->file_descriptor == NULL)
    1335                 :         {
    1336                 :           PDF_DEBUG_BASE("Invalid FD! Can't re-open");
    1337               0 :           ret_code = PDF_ECLOSED;
    1338                 :         }
    1339               0 :       else if(file_data->host_path == NULL)
    1340                 :         {
    1341                 :           PDF_DEBUG_BASE("Invalid file object. FD not NULL but empty path");
    1342               0 :           ret_code = PDF_ERROR;
    1343                 :         }
    1344                 :       else
    1345                 :         {
    1346               0 :           const pdf_char_t* mode_str = NULL;
    1347               0 :           ret_code = PDF_ERROR;
    1348                 :           /* Get the new mode string for freopen */
    1349               0 :           mode_str =__pdf_fsys_disk_get_mode_string(mode);
    1350                 :           PDF_DEBUG_BASE("Re-opening file '%s' with mode '%s'...",
    1351                 :                          file_data->host_path,
    1352                 :                          mode_str);
    1353                 : 
    1354               0 :           if(mode_str != NULL)
    1355                 :             {
    1356                 :               /* re-open the file */
    1357               0 :               file_data->file_descriptor = PDF_FREOPEN(file_data->host_path, \
    1358                 :                                                        mode_str,        \
    1359                 :                                                        file_data->file_descriptor);
    1360                 : 
    1361                 :               /* reset mode */
    1362               0 :               file_data->file_mode = mode;
    1363                 : 
    1364                 :               /* If got a good FD, set output data */
    1365               0 :               ret_code = ((file_data->file_descriptor != NULL) ? \
    1366                 :                           PDF_OK :                               \
    1367                 :                           __pdf_fsys_disk_get_status_from_errno(errno));
    1368                 :             }
    1369                 :         }
    1370                 :     }
    1371               0 :   return ret_code;
    1372                 : }
    1373                 : 
    1374                 : /*
    1375                 :  * Private functions
    1376                 :  */
    1377                 : 
    1378                 : static pdf_status_t
    1379                 : __pdf_fsys_disk_get_host_path (pdf_text_t path,
    1380                 :                                pdf_char_t **host_path,
    1381                 :                                pdf_size_t *host_path_size)
    1382              27 : {
    1383                 : #ifdef PDF_HOST_WIN32
    1384                 :   /* For W32, we will always use widechar functions, so Windows' wchar_t
    1385                 :    * implementation should be used (UTF-16LE) */
    1386                 :   pdf_char_t *data = NULL;
    1387                 :   pdf_size_t size = 0;
    1388                 : 
    1389                 :   if(pdf_text_get_unicode(&data,
    1390                 :                           &size,
    1391                 :                           path,
    1392                 :                           PDF_TEXT_UTF16_LE,
    1393                 :                           PDF_TEXT_UNICODE_WITH_NUL_SUFFIX) == PDF_OK)
    1394                 :     {
    1395                 :       *host_path = data;
    1396                 :       *host_path_size = size;
    1397                 :       return PDF_OK;
    1398                 :     }
    1399                 :   else
    1400                 :     return PDF_ERROR;
    1401                 : #else
    1402                 :   /* Call the pdf_text module to get a host-encoded version of the
    1403                 :    *  given path */
    1404              27 :   pdf_char_t *padded = NULL;
    1405              27 :   pdf_size_t padded_size = 0;
    1406                 : 
    1407              27 :   if(pdf_text_get_host(&padded,
    1408                 :                        &padded_size,
    1409                 :                        path,
    1410                 :                        pdf_text_get_host_encoding ()) == PDF_OK)
    1411                 :     {
    1412              27 :       *host_path = pdf_realloc(padded, padded_size+2);
    1413              27 :       if(*host_path != NULL)
    1414                 :         {
    1415              27 :           *host_path_size = padded_size + 1;
    1416              27 :           (*host_path)[(*host_path_size)-1] = '\0'; 
    1417              27 :           return PDF_OK;
    1418                 :         }
    1419                 :       else
    1420               0 :         return PDF_ENOMEM;
    1421                 :     }
    1422                 :   else
    1423               0 :     return PDF_ERROR;
    1424                 : #endif
    1425                 : }
    1426                 : 
    1427                 : 
    1428                 : static pdf_status_t
    1429                 : __pdf_fsys_disk_set_host_path (const pdf_char_t *host_path,
    1430                 :                                const pdf_size_t  host_path_size,
    1431                 :                                pdf_text_t *p_path)
    1432                 : {
    1433               0 :   if((host_path == NULL) || \
    1434                 :      (host_path_size == 0) || \
    1435                 :      (p_path == NULL))
    1436                 :     {
    1437               0 :       return PDF_EBADDATA;
    1438                 :     }
    1439                 : 
    1440                 : #ifdef PDF_HOST_WIN32
    1441                 :   /* For W32, we will always use widechar functions, so Windows' wchar_t
    1442                 :    * implementation should be used (UTF-16LE) */
    1443                 :   return pdf_text_new_from_unicode(host_path,
    1444                 :                                    host_path_size,
    1445                 :                                    PDF_TEXT_UTF16_LE,
    1446                 :                                    p_path);
    1447                 : #else
    1448                 :   /* Call the pdf_text module to get a host-encoded version of the
    1449                 :    *  given path */
    1450               0 :   return pdf_text_new_from_host(host_path,
    1451                 :                                 host_path_size,
    1452                 :                                 pdf_text_get_host_encoding (),
    1453                 :                                 p_path);
    1454                 : #endif
    1455                 : }
    1456                 : 
    1457                 : 
    1458                 : 
    1459                 : 
    1460                 : 
    1461                 : #ifndef PDF_HOST_WIN32
    1462                 : /* Posix-based open mode */
    1463                 : static const pdf_char_t *__pdf_fsys_open_mode_strings[PDF_FSYS_OPEN_MODE_MAX] = {
    1464                 :   /* PDF_FSYS_OPEN_MODE_INVALID  */ (pdf_char_t *)"",
    1465                 :   /* PDF_FSYS_OPEN_MODE_READ     */ (pdf_char_t *)"r",
    1466                 :   /* PDF_FSYS_OPEN_MODE_WRITE    */ (pdf_char_t *)"w",
    1467                 :   /* PDF_FSYS_OPEN_MODE_RW      */ (pdf_char_t *)"r+",
    1468                 : };
    1469                 : #else
    1470                 :   /* Windows portability note:
    1471                 :    *
    1472                 :    * Files are opened in "text mode" (with crlf translation) by
    1473                 :    * default.
    1474                 :    *
    1475                 :    * Although the "b" fopen option is supported by POSIX some old Unix
    1476                 :    * systems may not implement it, so we should use that option to
    1477                 :    * open files only while running in Windows.
    1478                 :    *
    1479                 :    * Also, note that the open modes are in UTF-16 for w32
    1480                 :    */
    1481                 : static const pdf_char_t *__pdf_fsys_open_mode_strings[PDF_FSYS_OPEN_MODE_MAX] = {
    1482                 :   /* PDF_FSYS_OPEN_MODE_INVALID  */ (pdf_char_t *)"\x00\x00",
    1483                 :   /* PDF_FSYS_OPEN_MODE_READ     */ (pdf_char_t *)"\x72\x00\x62\x00\x00\x00",
    1484                 :   /* PDF_FSYS_OPEN_MODE_WRITE    */ (pdf_char_t *)"\x77\x00\x62\x00\x00\x00",
    1485                 :   /* PDF_FSYS_OPEN_MODE_RW       */ (pdf_char_t *)"\x72\x00\x62\x00\x2B\x00\x00\x00",
    1486                 : };
    1487                 : #endif
    1488                 : 
    1489                 : 
    1490                 : 
    1491                 : 
    1492                 : static const pdf_char_t *
    1493                 : __pdf_fsys_disk_get_mode_string(const enum pdf_fsys_file_mode_e mode)
    1494                 : {
    1495              24 :   return (((mode >= PDF_FSYS_OPEN_MODE_FIRST) &&                        \
    1496                 :            (mode <= PDF_FSYS_OPEN_MODE_LAST)) ?                         \
    1497                 :           __pdf_fsys_open_mode_strings[mode] :                          \
    1498                 :           NULL);
    1499                 : }
    1500                 : 
    1501                 : 
    1502                 : 
    1503                 : #ifdef PDF_HOST_WIN32
    1504                 : 
    1505                 : #define PDF_MAX_W32_DEVICE_NAMES  32
    1506                 : static const pdf_char_t *device_names[PDF_MAX_W32_DEVICE_NAMES] = {
    1507                 :   (pdf_char_t *)"NUL",
    1508                 :   (pdf_char_t *)"CON",
    1509                 :   (pdf_char_t *)"PRN",
    1510                 :   (pdf_char_t *)"AUX",
    1511                 :   (pdf_char_t *)"COM1",
    1512                 :   (pdf_char_t *)"COM2",
    1513                 :   (pdf_char_t *)"COM3",
    1514                 :   (pdf_char_t *)"COM4",
    1515                 :   (pdf_char_t *)"COM5",
    1516                 :   (pdf_char_t *)"COM6",
    1517                 :   (pdf_char_t *)"COM7",
    1518                 :   (pdf_char_t *)"COM8",
    1519                 :   (pdf_char_t *)"COM9",
    1520                 :   (pdf_char_t *)"LPT1",
    1521                 :   (pdf_char_t *)"LPT2",
    1522                 :   (pdf_char_t *)"LPT3",
    1523                 :   (pdf_char_t *)"LPT4",
    1524                 :   (pdf_char_t *)"LPT5",
    1525                 :   (pdf_char_t *)"LPT6",
    1526                 :   (pdf_char_t *)"LPT7",
    1527                 :   (pdf_char_t *)"LPT8",
    1528                 :   (pdf_char_t *)"LPT9"
    1529                 : };
    1530                 : 
    1531                 : static pdf_bool_t
    1532                 : __pdf_fsys_disk_win32_device_p (pdf_text_t path)
    1533                 : {
    1534                 :   /* The following special "files", which access devices, exist in all
    1535                 :      directories, case-insensitively, and with all possible endings
    1536                 :      after a period or colon, excpets in pathnames that start with
    1537                 :      \\?\: */
    1538                 : 
    1539                 :   int i;
    1540                 :   pdf_bool_t device_p = PDF_FALSE;
    1541                 :   pdf_text_t device_name;
    1542                 :   pdf_status_t ret_code;
    1543                 : 
    1544                 :   device_p = PDF_FALSE;
    1545                 :   i = 0;
    1546                 :   while((! device_p) && \
    1547                 :         (i < PDF_MAX_W32_DEVICE_NAMES))
    1548                 :     {
    1549                 :       pdf_text_new_from_unicode (device_names[i],
    1550                 :                                  strlen ((char *)device_names[i]),
    1551                 :                                  PDF_TEXT_UTF8,
    1552                 :                                  &device_name);
    1553                 :       
    1554                 :       if (pdf_text_cmp (path, device_name, PDF_FALSE, &ret_code) == 0)
    1555                 :         {
    1556                 :           device_p = PDF_TRUE;
    1557                 :         }
    1558                 :       else
    1559                 :         {
    1560                 :           i++;
    1561                 :         }
    1562                 :       pdf_text_destroy (device_name);
    1563                 :     }
    1564                 : 
    1565                 :   return device_p;
    1566                 : }
    1567                 : 
    1568                 : #endif /* !PDF_HOST_WIN32 */
    1569                 : 
    1570                 : static pdf_status_t
    1571                 : __pdf_fsys_disk_get_status_from_errno(int _errno)
    1572               2 : {
    1573               2 :   switch (_errno)
    1574                 :     {
    1575                 :       case EINVAL:
    1576                 :       case ESPIPE:
    1577                 :       case EOVERFLOW:
    1578                 :       case EBADF:
    1579                 :       case EFAULT:
    1580                 :       case EFBIG:
    1581                 :         /* Bad data */
    1582               0 :         return PDF_EBADDATA;
    1583                 :       case EACCES:
    1584                 :       case EPERM:
    1585                 :       case EROFS:
    1586                 :       case ETXTBSY:
    1587                 :         /* Not enough permissions */
    1588               1 :         return PDF_EBADPERMS;
    1589                 :       case EISDIR:
    1590                 :       case ENAMETOOLONG:
    1591                 :       case ENOENT:
    1592                 :       case ENOTDIR:
    1593                 : #ifdef ELOOP
    1594                 :       case ELOOP:
    1595                 : #endif
    1596                 :         /* Invalid path name */
    1597               1 :         return PDF_EBADNAME;
    1598                 :       case ENOMEM:
    1599                 :         /* No memory */
    1600               0 :         return PDF_ENOMEM;
    1601                 :       case EEXIST:
    1602                 :         /* File Exists */
    1603               0 :         return PDF_EEXIST;
    1604                 :       case ENOTEMPTY:
    1605                 :         /* Not empty */
    1606               0 :         return PDF_ENOTEMPTY;
    1607                 :       case EAGAIN:
    1608                 :         /* non-blocking descriptor and blocking writing
    1609                 :            requested */
    1610               0 :         return PDF_EAGAIN;
    1611                 :       case ENOSPC:
    1612                 :         /* Not enough room in disk */
    1613               0 :         return PDF_ENOSPC;
    1614                 :       default:
    1615                 :         /* Other error */
    1616               0 :         return PDF_ERROR;
    1617                 :     }
    1618                 : }
    1619                 : 
    1620                 : 
    1621                 : /* End of pdf-fsys-disk.c */

Generated by: LTP GCOV extension version 1.6