xref: /PHP-8.3/ext/standard/tests/file/file.inc (revision 9b07b013)
1<?php
2/* Header file for common file test functions
3     Following functions are provided :
4       create_files() : create files with specified contents
5       delete_files() : delete files
6       create_links() : crate links of different types
7       delete_links() : delete links
8       fill_files()   : fill file with specified contents
9       change_file_perms() : Change permission of files
10       fill_buffer()  : fills buffer with specified contents
11       compare_self_stat() : compares the first 13 elements of the
12                            stat with the corresponding named key values of
13                            the same stat.
14       compare_stats() : Compares two stat values
15
16*/
17
18const FILE_NOT_FOUND = 2;
19
20/*
21 Function: bool create_file(string $filename, string $mode = "w");
22 Description: creates a new file using fopen() call
23   $filename = Name of the file
24   $mode = Mode as specified in fopen call, read documentation of fopen() call for more info
25
26 Returns:
27   true on success, false otherwise
28*/
29function create_file($filename, $mode = "w") {
30  $file_handle = fopen ($filename, $mode);
31  if ( $file_handle == false )
32    return false;
33  fclose($file_handle);
34  return true;
35}
36
37/*
38 Function : bool fill_buffer(string &$buffer, string $fill_type, int $fill_size);
39 Description: Fills the $buffer with data as specified with requested size.
40   $buffer = buffer to be filled
41   $fill_type:
42       "text" = fills with string of size $file_size
43       "numeric" = fills with numeric value of size $file_size
44       "text_with_new_line" = similar to "text" fill type but writes with new line
45       "alphanumeric" = fills with alphnumeric values
46 Returns: true on success, false on invalid fill type
47*/
48function fill_buffer(&$buffer, $fill_type, $fill_size) {
49
50  if ( $fill_type == "text" ) {
51    $data = "text ";
52    $size_divider = strlen($data);
53    $add_value = strlen($data);
54  } else if ( $fill_type == "text_with_new_line" ) {
55    $data = "line\nline of text\n";
56    $size_divider = strlen($data);
57    $add_value = strlen($data);
58  } else if ( $fill_type == "alphanumeric" ) {
59    $data = "ab12 ";
60    $size_divider = strlen($data);
61    $add_value = strlen($data);
62  } else if ( $fill_type == "numeric" ) {
63    $data = 2;
64    $size_divider = 1;
65    $add_value = 0;
66  } else {
67    // invalid fill type;
68    return false;
69  }
70
71  $tmp_buff = str_repeat($data, (int)(($fill_size/$size_divider) + $add_value) );
72
73  if ( strlen($tmp_buff) > $fill_size ) {
74    $buffer = substr($tmp_buff, 0, $fill_size);
75  } else {
76    $buffer = $tmp_buff;
77  }
78
79  return true;
80}
81
82/*
83 Function : bool fill_file(resource $file_handle, string $fill_type, string $file_size);
84 Description: Fills the file with data as specified with requested size.
85   $file_handle = file handle, opened with write options,
86   $fill_type:
87       "text" = fills with string of size $file_size
88       "numeric" = fills with numeric value of size $file_size
89       "empty" = no fill operation performed, returns true
90       "text_with_new_line" = similar to "text" fill type but writes with new line
91       "alphanumeric" = fills with alphnumeric values
92 Returns: true on success, false on failure & invalid fill type
93*/
94
95function fill_file($file_handle, $fill_type, $file_size) {
96
97  if ( $fill_type == "empty" ) {
98    // no fill required, return true
99    return true;
100  } if ( $fill_type == "text" ) {
101    $data = "text ";
102    $size_divider = strlen($data);
103    $add_value = strlen($data);
104  } else if ( $fill_type == "text_with_new_line" ) {
105    $data = "line\nline of text\n";
106    $size_divider = strlen($data);
107    $add_value = strlen($data);
108  } else if ( $fill_type == "alphanumeric" ) {
109    $data = "ab12 ";
110    $size_divider = strlen($data);
111    $add_value = strlen($data);
112  } else if ( $fill_type == "numeric" ) {
113    $data = 2;
114    $size_divider = 1;
115    $add_value = 0;
116  } else {
117    // invalid fill type;
118    return false;
119  }
120
121  // write in terms of a chunk of 1 K to avoid memory size overflow
122  $size = $file_size;
123  $chunk_size = 1024;
124  if ( $size > $chunk_size ) {
125    $loop_count = 1;
126    do {
127      $loop_count ++;
128      if ( $size <= $chunk_size ) {
129        $chunk_size = $size;
130      }
131      $num_values = str_repeat($data, (int) (($chunk_size/$size_divider) + $add_value) );
132      $bytes_written = fwrite($file_handle, $num_values, $chunk_size);
133      if ( $bytes_written != $chunk_size ) {
134            return false;
135      }
136      $size -= $chunk_size;
137    } while ( $size > 0 );
138  } else {
139    $num_values = str_repeat($data, (int) (($chunk_size/$size_divider) + $add_value) );
140    $bytes_written = fwrite($file_handle, $num_values, $file_size);
141    if ( $bytes_written != $file_size ) {
142      return false;
143    }
144  }
145
146  // successful, return true
147  return true;
148}
149
150/*
151 Function: int change_file_perms(string $file_path, int $count = 1, int $perms = 0755,
152                                 string $name_prefix = "file",
153                                 string $name_suffix = 1, $file_extension = ".tmp");
154 Description: changes file permission for given file(s).
155   $file_path = dir path where file exists
156   $count = no. of files, default is 1
157   $perms = new permission of the file, similar to $mode args of chmod() call
158   $name_prefix = common name prefix, default is "file"
159   $name_suffix = suffix to end the common name given in name_prefix to create
160      a unique name. default is 1.
161   $file_extension = default is .tmp
162 Returns:
163   Integer, Count of total files permission changed.
164*/
165function change_file_perms($file_path,
166                           $count = 1,
167                           $perms = 0755,
168                           $name_prefix = "file",
169                           $name_suffix = 1,
170                           $file_extension = ".tmp" )
171{
172  $changed = 0;
173
174  if( $count <= 0 )
175    return $changed;
176
177  if ( $name_suffix <= 0)
178    $name_suffix = 1;
179
180  for($loop_counter = 1; $loop_counter <= $count; $loop_counter++) {
181    $filename = $file_path."/".$name_prefix.$name_suffix.$file_extension;
182    if( chmod($filename, $perms) )
183      $changed++;
184    $name_suffix++;
185  }
186  return $changed;
187}
188
189/*
190 Function: array create_files( string $file_path,
191                               int $count = 1,
192                               string $content_type = "numeric",
193                               int $permission = 0755,
194                               int $size = 1,
195                               string $mode = "w",
196                               string $name_prefix = "file",
197                               int $name_suffix = 1,
198                               string $flag = "kilobytes"
199                               string $file_extension = ".tmp"
200                             );
201 Description: Creates given number of files with specified mode and
202   permissions. File is filled with content of size specified.
203   $file_path = dir where files will be created
204   $name_prefix = prefix to be used for names, name is suffix with a
205     unique numeric value to make the file name unique, default = file
206   $name_suffix = suffix to be used for the name, default = 1
207   $count = total no. of files to be created, default = 1
208   $mode = file open mode as specified in fopen() call. Do not use
209     modes used for only reading the file. Default = "w"
210   $permission = An octal number, This should be similar to $mode
211     specified in chmod() call.
212   $content_type = Specify type of the content to fill in the file.
213     "numeric" = fill file with numeric values
214     "text" = fill file with regular text
215     "empty" = empty file
216     "text_with_new_line" = similar to text fill type, but writes with new line char
217     "alphanumeric" = fill file with alpha numeric text
218     If improper $content type is specified, file is created as empty
219   $size = size of the fill in terms of kilobyte, i.e size of the file.
220           if $flag is specified as "byte", then then given size is taken in bytes
221   $flag = specify if size has to be treated as no of total bytes or
222           multiple of KB.
223     "kilobytes" = take size in terms of multiple of KB
224     "byte" = take size in terms of bytes
225   $file_extension = default is .tmp
226
227 Returns:
228   An array with following key value pair:
229     created => total file created
230     filled => total files filled
231     perms_changed => total files permission changed
232*/
233function create_files( $file_path,
234                       $count = 1,
235                       $content_type = "numeric",
236                       $permission = 0755,
237                       $size = 1,
238                       $mode = "w",
239                       $name_prefix = "file",
240                       $name_suffix = 1,
241                       $flag = "kilobytes",
242                       $file_extension = ".tmp"
243                     )
244{
245  $return_value = array('created' => 0, 'filled' => 0, 'perms_changed' => 0);
246
247  //ensure that suffix is a +ve integer
248  if ($name_suffix <= 0) {
249    $name_suffix = 1;
250  }
251
252  // check for proper size
253  if ( $size == 0 )
254    return $return_value;
255
256  // prepare the size based on flag
257  $file_size = $size;
258  if ( $flag == "kilobytes" ) {
259    $file_size = $file_size * 1024;
260  }
261
262  $tmp_name_suffix = $name_suffix;
263  // create the files with specified mode and permission
264  for($file_created_count = 1; $file_created_count <= $count; $file_created_count ++) {
265    $filename = $file_path."/".$name_prefix.$tmp_name_suffix.$file_extension;
266
267    $status = create_file($filename, $mode);
268
269    $tmp_name_suffix++;
270
271    if ($status == true) {
272      $return_value['created']++;
273    }
274    else {
275      return $return_value;
276    }
277  }
278
279  if ( $content_type == "empty" ) {
280    $return_value['filled'] = $count;
281  } else {
282    // fill the file with specifiec type of data and size
283    $tmp_name_suffix = $name_suffix;
284    for($loop_counter = 1; $loop_counter <= $count; $loop_counter ++) {
285      $filename = $file_path."/".$name_prefix.$tmp_name_suffix.$file_extension;
286      $file_handle = fopen($filename, $mode);
287      if($file_handle == false) {
288        fclose($file_handle);
289        return $return_value;
290      } // end of if
291
292      // call fill_file() to fill the file
293      if( fill_file($file_handle, $content_type, $file_size) )
294        $return_value['filled']++;
295
296      fclose($file_handle);
297
298      $tmp_name_suffix++;
299    } // end of for
300  }
301
302  // change all file's permissions
303  $return_value['perms_changed'] = change_file_perms($file_path, $count, $permission, $name_prefix,
304                                                     $name_suffix, $file_extension);
305
306  return $return_value;
307}
308
309
310/*
311 Function: function create_links( $file_path,
312               $filename,
313                       $link_count = 1,
314                       $link_type = "soft",
315                       $link_size = 1024,
316                       $link_name_prefix = "link",
317                       $link_name_suffix = 1,
318                       $link_file_content = "text",
319                       $link_perms = 0755,
320                       $link_file_extension = ".tmp"
321                     );
322
323 Description: Creates given number of links with specified mode and
324   permissions.Link is filled with content of size specified.
325   $file_path = location of the file and where links need to be created
326   $link_name_prefix = prefix to be used for names, name is suffix with a
327     unique numeric value to make the file name unique, default = link
328   $link_name_suffix = suffix to be used for the name, default = 1
329   $link_count = total no. of links to be created to given file, default = 1
330   $link_perms = An octal number, This should be similar to $mode
331     specified in chmod() call.
332   $link_file_content = Type of the content to fill in the file.
333     numeric = fill file with numeric values
334     text = fill file with regular text
335     text_with_new_line = same as text but new lines are written
336     alphanumeric = fill with alphanumeric text
337     If imporper $content type is specified, file is created as empty
338   $size = size of the fill in terms of kilobyte, i.e size of the file.
339   $link_type = type of the link to be created
340      "soft" = soft link
341      "hard" = hard link
342   $filename = file used to create a link on
343
344 Returns:
345   An array with following key value pair:
346     created => total file created
347     filled => total files filled, always returned as 1
348     perms_changed => total files permission changed
349*/
350function create_links($file_path,
351                      $filename,
352                      $link_count = 1,
353                      $link_type = "soft",
354                      $link_size = 1024,
355                      $link_name_prefix = "link",
356                      $link_name_suffix = 1,
357                      $link_file_content = "text",
358                      $link_perms = 0755,
359                      $link_file_extension = ".tmp"
360                     )
361{
362  $return_value = array('created' => 0, 'filled' => 0, 'perms_changed' => 0);
363  $tmp_name_suffix = $link_name_suffix;
364  $src_filename = $file_path."/".$filename;
365  switch( $link_type ) {
366    default :
367    case "soft" :  // create a soft link
368      for($link_created_count = 1; $link_created_count <= $link_count; $link_created_count++) {
369        $linkname = $file_path."/".$link_name_prefix.$tmp_name_suffix.$link_file_extension;
370        $status = symlink( $src_filename, $linkname);
371        $tmp_name_suffix++;
372        if ($status) {
373          $return_value['created']++;
374        }
375        else {
376          $return_value;
377        }
378      }
379      break;
380
381    case "hard" :  // create a hard link
382      for($link_created_count = 1; $link_created_count <= $link_count; $link_created_count++) {
383        $linkname = $file_path."/".$link_name_prefix.$tmp_name_suffix.$link_file_extension;
384        $status = link($src_filename, $linkname);
385        $tmp_name_suffix++;
386        if ($status) {
387          $return_value['created']++;
388        }
389        else {
390          $return_value;
391        }
392      }
393      break;
394  }
395
396  if ( $link_file_content == "empty" ) {
397    $return_value['filled'] = 1;
398    return $return_value;
399  }
400
401  // fill the file with specific type of data and size
402  $tmp_name_suffix = $link_name_suffix;
403  $linkname = $file_path."/".$link_name_prefix.$tmp_name_suffix.$link_file_extension;
404  $file_handle = fopen($linkname, "w");
405  if($file_handle == false) {
406    return $return_value;
407  } // end of if
408
409  // call fill_file() to fill the file
410  if( fill_file($file_handle, $link_file_content, $link_size) )
411    $return_value['filled']++;
412
413  // close the link
414  fclose($file_handle);
415
416  // change the permission of the link file, only if hard link.
417  // this is not applicable to soft links
418  if( $link_type == "hard" ) {
419    $return_value['perms_changed'] = change_file_perms($file_path,
420                                                        $link_count,
421                                                        $link_perms,
422                                                        $link_name_prefix,
423                                                        $link_name_suffix,
424                                                        $link_file_extension );
425  }
426
427  return $return_value;
428}
429
430/*
431 Function: bool delete_file(string $filename);
432 Description: delete a given file if exists
433 Returns: true on success
434          false on failure
435          FILE_NOT_FOUND if file doesn't exist
436*/
437function delete_file($filename) {
438  // check if file exists
439  if ( file_exists($filename) ) {
440    if ( unlink($filename) )
441      return true;
442    else
443      return false;
444  }
445  return FILE_NOT_FOUND;
446}
447
448/*
449 Function: array delete_files(string $file_path, int $count = 1, string $name_prefix = "file",
450                              int name_suffix = 1, $file_extension = ".tmp" );
451 Description: Deletes given number of files if exists.
452   $file_path = location of the files
453   $name_prefix = prefix for the filename, rest of the name is incremental(increment by 1 only)
454     numeric starting from suffix up to count
455   $count = number of files to be deleted
456   $name_suffix = first numeric suffix in the name
457 Returns: An array with following key/value pair
458   deleted = Number of files deleted.
459   notfound = Count of non existing file
460   failed = Count of failed to delete
461*/
462function delete_files($file_path,
463                      $count = 1,
464                      $name_prefix = "file",
465                      $name_suffix = 1,
466                      $file_extension = ".tmp")
467{
468  $return_value = array ('deleted' => 0, 'notfound' => 0, 'failed' => 0);
469
470  if ( $name_suffix < 1 )
471    $name_suffix = 1;
472  for($loop_counter = 1; $loop_counter <= $count; $loop_counter++) {
473    $filename = $file_path."/".$name_prefix.$name_suffix.$file_extension;
474    $name_suffix++;
475    $status = delete_file($filename);
476    if($status == true) {
477      $return_value['deleted']++;
478    } else if($status == FILE_NOT_FOUND) {
479      $return_value['notfound']++;
480    } else {
481      $return_value['failed']++;
482    }
483
484  } // end of for
485  return $return_value;
486}
487
488/*
489 Function: array delete_links( $file_path,
490                               $link_file_count,
491                               $link_name_prefix,
492                               $link_name_suffix,
493                               $link_file_extension );
494 Description: Deletes given number of links if exists. Uses delete_files() function
495   $file_path = location of link files
496   $link_file_count = Number of link files
497   $link_name_prefix = prefix for the linkname, rest of the name is incremental(increment by 1 only)
498     numeric starting from $link_name_suffix up to count
499   $link_name_suffix = first numeric suffix in the name
500
501 Returns: An array with following key/value pair
502   deleted = Number of links deleted.
503   notfound = Count of non existing link
504   failed = Count of failed to delete
505*/
506function delete_links($file_path,
507                      $link_file_count = 1,
508                      $link_name_prefix = "link",
509                      $link_name_suffix = 1,
510                      $link_file_extension = ".tmp")
511{
512   // call the delete files to delete links
513   $return_value = delete_files( $file_path,
514                                 $link_file_count,
515                                 $link_name_prefix,
516                                 $link_name_suffix,
517                                 $link_file_extension );
518   return $return_value;
519}
520
521
522
523/*
524 Prototype:
525  function compare_self_stat( array $stat );
526 Description:
527  Compares the each of the first 13 values of the stat array with the
528  corresponding next 13 values of the same stat for equality
529  $stat = stat array
530
531 Returns: true when all of them match, false otherwise
532*/
533function compare_self_stat( array $stat )
534{
535  //return value
536  $return_value = true;
537
538  // named keys present in a stat
539  $string_keys = array("dev", "ino", "mode", "nlink", "uid", "gid",
540                       "rdev", "size", "atime", "mtime", "ctime",
541                       "blksize", "blocks");
542
543  // first numeric key
544  $key = 0;
545
546  // compare the values in the stat, which are accessed using numeric key with
547  // values accessed using string keys
548  foreach($string_keys as $str_key)
549  {
550    if($stat[$key] != $stat[$str_key]) {
551      echo "Error: stat[$key] doesn't match with stat[$str_key]\n";
552      $flag = false;
553      $key++;
554    }
555    else {
556      $key++;
557    }
558  } // end of foreach
559
560  // if the $return_value is false, i.e all the element do not match then
561  // dump the stat array so that its easy to figure out the error
562  if ($return_value == false ) {
563    echo "\n Dumping stat array ...\n";
564    var_dump($stat);
565  }
566
567  return $return_value;
568}// end of compare_self_stat
569
570/*
571Prototype:
572  function compare_stats( array $stat1, array $stat2, array $fields,
573                          [string $op = "==", [ bool $flag = false] ]);
574Description:
575  Compares two stat values, stat value should be obtained by stat/lstat
576  $stat1 = first stat array
577  $stat2 = second stat array
578  $op = type of the comparison to be perform between elements of stat1 and stat2
579    "!=" compare for not equal
580    "==" compare for equality
581    ">"  if each element of stat1 is > than stat2
582    "<"  if each element of stat1 is < than stat2
583  $fields = contains the key of the elements that needs to be compared.
584            type of the comparison is based on $op argument value
585  $flag = specify true to dump the stat1 and stat2
586*/
587
588$all_stat_keys = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
589                       "dev", "ino", "mode", "nlink", "uid", "gid",
590                       "rdev", "size", "atime", "mtime", "ctime",
591                       "blksize", "blocks");
592
593function compare_stats($stat1, $stat2, $fields, $op = "==", $flag = false ) {
594  $stat_time_diff_keys = array(8, 'atime');
595
596  // dump the stat if requested
597  if ( $flag == true ) {
598    var_dump($stat1);
599    var_dump($stat2);
600  }
601
602  $result = true;
603
604  // compare values of given key from each stat array
605  for($index = 0; $index < count($fields); $index++)
606  {
607    switch( $op )
608    {
609       case "==":
610         if ( $stat1[ $fields[$index] ] != $stat2[ $fields[$index] ] ) {
611          if ( ! in_array( $fields[$index], $stat_time_diff_keys ) ) {
612            $result = false;
613            echo "Error: stat1 do not match with stat2 at key value: $fields[$index]\n";
614          } elseif (abs($stat1[ $fields[$index] ] - $stat2[ $fields[$index] ]) > 2) {
615            $result = false;
616            echo "Error: stat1 differs too much from stat2 at key value: $fields[$index]\n";
617          }
618         }
619         break;
620
621       case "!=":
622         if ( $stat1[ $fields[$index] ] != $stat2[ $fields[$index] ] ) {
623           // do nothing as its not equal, else will take care of if equal
624         } else {
625           $result = false;
626           echo "Error: stat1 equals stat2 at key value: $fields[$index]\n";
627         }
628         break;
629
630       case ">":
631         if ( $stat1[ $fields[$index] ] <= $stat2[ $fields[$index] ] ) {
632           $result = false;
633           echo "Error: stat1 is not greater than stat2 at key value: $fields[$index]\n";
634         }
635         break;
636
637       case "<":
638         if ( $stat1[ $fields[$index] ] >= $stat2[ $fields[$index] ] ) {
639           $result = false;
640           echo "Error: stat1 is not lesser than stat2 at key value: $fields[$index]\n";
641         }
642         break;
643    }
644  }
645  // if the result is false(i.e values are not as expected),
646  // dump the stat array so that easy to figure out the error
647  if ( $result == false ) {
648    echo "\n Dumping stat array 1...\n";
649    var_dump($stat1);
650    echo "\n Dumping stat array 2...\n";
651    var_dump($stat2);
652  }
653
654  return $result;
655}
656
657?>
658