/[osn-commons]/trunk/uar/uar.c
ViewVC logotype

Diff of /trunk/uar/uar.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 24 by rakinar2, Mon Aug 5 17:15:48 2024 UTC revision 25 by rakinar2, Tue Aug 6 13:06:45 2024 UTC
# Line 12  Line 12 
12  #include <stdio.h>  #include <stdio.h>
13  #include <stdlib.h>  #include <stdlib.h>
14  #include <string.h>  #include <string.h>
15    #include <strings.h>
16  #include <sys/stat.h>  #include <sys/stat.h>
17  #include <sys/types.h>  #include <sys/types.h>
18  #include <unistd.h>  #include <unistd.h>
# Line 24  Line 25 
25  #    include <limits.h>  #    include <limits.h>
26  #endif  #endif
27    
28    #define UAR_ROOT_DIR_NAME 0x01
29    
30  const unsigned char UAR_MAGIC[] = { 0x99, 'U', 'A', 'R' };  const unsigned char UAR_MAGIC[] = { 0x99, 'U', 'A', 'R' };
31    
32  struct uar_header  struct uar_header
# Line 45  enum uar_file_type Line 48  enum uar_file_type
48  struct uar_file  struct uar_file
49  {  {
50      enum uar_file_type type;      enum uar_file_type type;
51        int __pad1;
52      char *name;      char *name;
53      uint64_t namelen;      uint64_t namelen;
54      uint32_t offset;      uint64_t offset;
55      union      union
56      {      {
57          uint64_t size;          uint64_t size;
# Line 58  struct uar_file Line 62  struct uar_file
62          } linkinfo;          } linkinfo;
63      } data;      } data;
64      mode_t mode;      mode_t mode;
65        int __pad2;
66  };  };
67    
68  struct uar_archive  struct uar_archive
# Line 109  uar_has_error (const struct uar_archive Line 114  uar_has_error (const struct uar_archive
114  }  }
115    
116  struct uar_archive *  struct uar_archive *
117    uar_create (void)
118    {
119        struct uar_archive *uar = malloc (sizeof (struct uar_archive));
120    
121        if (uar == NULL)
122            return NULL;
123    
124        uar->is_stream = false;
125        uar->buffer = NULL;
126        uar->ecode = UAR_SUCCESS;
127        uar->header.size = 0;
128        memcpy (uar->header.magic, UAR_MAGIC, 4);
129        uar->header.version = 1;
130        uar->header.flags = 0;
131        uar->header.nfiles = 0;
132        uar->files = NULL;
133    
134        return uar;
135    }
136    
137    struct uar_archive *
138  uar_open (const char *filename)  uar_open (const char *filename)
139  {  {
140      struct uar_archive *uar = NULL;      struct uar_archive *uar = NULL;
# Line 116  uar_open (const char *filename) Line 142  uar_open (const char *filename)
142      int cerrno;      int cerrno;
143    
144      errno = 0;      errno = 0;
145      uar = malloc (sizeof (struct uar_archive));      uar = uar_create ();
146    
147      if (uar == NULL)      if (uar == NULL)
148          return NULL;          return NULL;
# Line 189  uar_open (const char *filename) Line 215  uar_open (const char *filename)
215                      goto uar_open_ret;                      goto uar_open_ret;
216                  }                  }
217    
218              file->name = malloc (file->namelen);              file->name = malloc (file->namelen + 1);
219    
220              if (file->name == NULL)              if (file->name == NULL)
221                  {                  {
# Line 203  uar_open (const char *filename) Line 229  uar_open (const char *filename)
229                      goto uar_open_ret;                      goto uar_open_ret;
230                  }                  }
231    
232                file->name[file->namelen] = 0;
233              uar->files[i] = file;              uar->files[i] = file;
234          }          }
235    
# Line 228  uar_open_ret: Line 255  uar_open_ret:
255  }  }
256    
257  void  void
258  uar_close (struct uar_archive *uar)  uar_file_destroy (struct uar_file *file)
259  {  {
260      if (uar == NULL)      if (file == NULL)
261          return;          return;
262    
263      free (uar->buffer);      free (file->name);
264      free (uar->files);      free (file);
     free (uar);  
265  }  }
266    
267  struct uar_archive *  void
268  uar_create ()  uar_close (struct uar_archive *uar)
269  {  {
     struct uar_archive *uar = malloc (sizeof (struct uar_archive));  
   
270      if (uar == NULL)      if (uar == NULL)
271          return NULL;          return;
272    
273      uar->is_stream = false;      free (uar->buffer);
     uar->buffer = NULL;  
     uar->header.size = sizeof (struct uar_header);  
     memcpy (uar->header.magic, UAR_MAGIC, 4);  
     uar->header.version = 1;  
     uar->header.flags = 0;  
     uar->header.nfiles = 0;  
274    
275      return uar;      for (uint64_t i = 0; i < uar->header.nfiles; i++)
276            {
277                struct uar_file *file = uar->files[i];
278                uar_file_destroy (file);
279            }
280    
281        free (uar->files);
282        free (uar);
283  }  }
284    
285  bool  bool
# Line 285  uar_file_create (const char *name, uint6 Line 310  uar_file_create (const char *name, uint6
310                   uint32_t offset)                   uint32_t offset)
311  {  {
312      struct uar_file *file;      struct uar_file *file;
313        int cerrno;
314      assert (namelen < PATH_MAX);      assert (namelen < PATH_MAX);
315    
316      file = malloc (sizeof (struct uar_file));      file = malloc (sizeof (struct uar_file));
# Line 292  uar_file_create (const char *name, uint6 Line 318  uar_file_create (const char *name, uint6
318      if (file == NULL)      if (file == NULL)
319          return NULL;          return NULL;
320    
321        bzero (file, sizeof (struct uar_file));
322    
323      file->type = UF_FILE;      file->type = UF_FILE;
324      file->mode = 0644;      file->mode = 0644;
325      file->name = malloc (namelen + 1);      file->name = malloc (namelen + 1);
326    
327      if (file->name == NULL)      if (file->name == NULL)
328          {          {
329                cerrno = errno;
330              free (file);              free (file);
331                errno = cerrno;
332              return NULL;              return NULL;
333          }          }
334    
# Line 311  uar_file_create (const char *name, uint6 Line 341  uar_file_create (const char *name, uint6
341      return file;      return file;
342  }  }
343    
 void  
 uar_file_destroy (struct uar_file *file)  
 {  
     if (file == NULL)  
         return;  
   
     free (file->name);  
     free (file);  
 }  
   
344  struct uar_file *  struct uar_file *
345  uar_add_file (struct uar_archive *restrict uar, const char *name,  uar_add_file (struct uar_archive *restrict uar, const char *name,
346                const char *path)                const char *path)
# Line 347  uar_add_file (struct uar_archive *restri Line 367  uar_add_file (struct uar_archive *restri
367          }          }
368    
369      fseek (stream, 0, SEEK_END);      fseek (stream, 0, SEEK_END);
370      uint64_t size = ftell (stream);      long size = ftell (stream);
371    
372        if (size < 0)
373            {
374                uar_set_error (uar, UAR_IO_ERROR);
375                fclose (stream);
376                return NULL;
377            }
378    
379      fseek (stream, 0, SEEK_SET);      fseek (stream, 0, SEEK_SET);
380    
381      struct uar_file *file      struct uar_file *file
# Line 378  uar_add_file (struct uar_archive *restri Line 406  uar_add_file (struct uar_archive *restri
406              return NULL;              return NULL;
407          }          }
408    
409      if (fread (uar->buffer + file->offset, size, 1, stream) != 1)      if (size != 0 && fread (uar->buffer + file->offset, size, 1, stream) != 1)
410          {          {
411              uar_set_error (uar, UAR_IO_ERROR);              uar_set_error (uar, UAR_IO_ERROR);
412              fclose (stream);              fclose (stream);
# Line 405  path_concat (const char *p1, const char Line 433  path_concat (const char *p1, const char
433  }  }
434    
435  struct uar_file *  struct uar_file *
436  uar_add_dir (struct uar_archive *uar, const char *name, const char *path)  uar_add_dir (struct uar_archive *uar, const char *dname, const char *path)
437  {  {
438      assert (uar != NULL && "uar is NULL");      assert (uar != NULL && "uar is NULL");
439      assert (name != NULL && "name is NULL");      assert (dname != NULL && "dname is NULL");
440      assert (path != NULL && "path is NULL");      assert (path != NULL && "path is NULL");
441      assert (!uar->is_stream && "uar in non-stream mode is not supported yet");      assert (!uar->is_stream && "uar in non-stream mode is not supported yet");
442    
443      uint64_t namelen = strlen (name);      char *name = (char *) dname;
444        bool free_name = false;
445        int cerrno;
446        uint64_t namelen;
447    
448        if (strcmp (name, ".") == 0)
449            {
450                name = malloc (2);
451                name[0] = UAR_ROOT_DIR_NAME;
452                name[1] = 0;
453                free_name = true;
454                namelen = 1;
455            }
456        else
457            namelen = strlen (name);
458    
459      if (namelen >= PATH_MAX)      if (namelen >= PATH_MAX)
460          {          {
# Line 467  uar_add_dir (struct uar_archive *uar, co Line 509  uar_add_dir (struct uar_archive *uar, co
509    
510              if (stat (fullpath, &stinfo) != 0)              if (stat (fullpath, &stinfo) != 0)
511                  {                  {
                     int current_errno = errno;  
512                      uar_set_error (uar, UAR_IO_ERROR);                      uar_set_error (uar, UAR_IO_ERROR);
513                      uar_file_destroy (dir_file);                      goto uar_add_dir_error;
                     closedir (dir);  
                     free (fullpath);  
                     free (fullname);  
                     errno = current_errno;  
                     return NULL;  
514                  }                  }
515    
516              if (S_ISREG (stinfo.st_mode))              if (S_ISREG (stinfo.st_mode))
# Line 484  uar_add_dir (struct uar_archive *uar, co Line 520  uar_add_dir (struct uar_archive *uar, co
520    
521                      if (file == NULL)                      if (file == NULL)
522                          {                          {
523                              int current_errno = errno;                              goto uar_add_dir_error;
                             uar_file_destroy (dir_file);  
                             closedir (dir);  
                             free (fullpath);  
                             free (fullname);  
                             errno = current_errno;  
                             return NULL;  
524                          }                          }
525    
526                      file->mode = stinfo.st_mode & 07777;                      file->mode = stinfo.st_mode & 07777;
# Line 503  uar_add_dir (struct uar_archive *uar, co Line 533  uar_add_dir (struct uar_archive *uar, co
533    
534                      if (direntry == NULL)                      if (direntry == NULL)
535                          {                          {
536                              int current_errno = errno;                              goto uar_add_dir_error;
                             uar_file_destroy (dir_file);  
                             closedir (dir);  
                             free (fullpath);  
                             free (fullname);  
                             errno = current_errno;  
                             return NULL;  
537                          }                          }
538    
539                      direntry->mode = stinfo.st_mode & 07777;                      direntry->mode = stinfo.st_mode & 07777;
# Line 519  uar_add_dir (struct uar_archive *uar, co Line 543  uar_add_dir (struct uar_archive *uar, co
543                  assert (false && "Not supported");                  assert (false && "Not supported");
544    
545              free (fullpath);              free (fullpath);
546          }              free (fullname);
547    
548      closedir (dir);              continue;
549    
550            uar_add_dir_error:
551                cerrno = errno;
552                uar_file_destroy (dir_file);
553                free (fullpath);
554                free (fullname);
555                errno = cerrno;
556                goto uar_add_dir_end;
557            }
558    
559      dir_file->type = UF_DIR;      dir_file->type = UF_DIR;
560      dir_file->data.size = dir_size;      dir_file->data.size = dir_size;
561    
562    uar_add_dir_end:
563        cerrno = errno;
564        closedir (dir);
565    
566        if (free_name)
567            free (name);
568    
569        errno = cerrno;
570      return dir_file;      return dir_file;
571  }  }
572    
# Line 582  uar_debug_print (const struct uar_archiv Line 623  uar_debug_print (const struct uar_archiv
623                      : file->type == UF_DIR ? "directory"                      : file->type == UF_DIR ? "directory"
624                                             : "link",                                             : "link",
625                      i);                      i);
626              printf ("    name: \033[1m%s%s\033[0m\n", file->name,              printf ("    name: \033[1m%s%s%s\033[0m\n",
627                        file->name[0] == UAR_ROOT_DIR_NAME ? "/" : "",
628                        file->name[0] == UAR_ROOT_DIR_NAME ? file->name + 2
629                                                           : file->name,
630                      file->type == UF_DIR    ? "/"                      file->type == UF_DIR    ? "/"
631                      : file->type == UF_LINK ? "@"                      : file->type == UF_LINK ? "@"
632                                              : "");                                              : "");
633              printf ("    offset: %u\n", file->offset);              printf ("    offset: %lu\n", file->offset);
634              printf ("    mode: %04o\n", file->mode);              printf ("    mode: %04o\n", file->mode);
635    
636              switch (file->type)              switch (file->type)
# Line 643  uar_write (struct uar_archive *uar, cons Line 687  uar_write (struct uar_archive *uar, cons
687                  }                  }
688          }          }
689    
690      if (fwrite (uar->buffer, uar->header.size, 1, stream) != 1)      if (fwrite (uar->buffer, 1, uar->header.size, stream) != uar->header.size)
691          {          {
692              uar_set_error (uar, UAR_IO_ERROR);              uar_set_error (uar, UAR_IO_ERROR);
693              fclose (stream);              fclose (stream);
# Line 657  uar_write (struct uar_archive *uar, cons Line 701  uar_write (struct uar_archive *uar, cons
701  const char *  const char *
702  uar_get_file_name (const struct uar_file *file)  uar_get_file_name (const struct uar_file *file)
703  {  {
704      return file->name;      return file->name[0] == UAR_ROOT_DIR_NAME
705                   ? file->namelen == 1 ? "/" : file->name + 1
706                   : file->name;
707  }  }
708    
709  bool  bool
# Line 677  uar_extract (struct uar_archive *uar, co Line 723  uar_extract (struct uar_archive *uar, co
723              if (callback != NULL && !callback (file))              if (callback != NULL && !callback (file))
724                  return false;                  return false;
725    
726                char *name = file->name;
727    
728                if (name[0] == UAR_ROOT_DIR_NAME)
729                    name += 2;
730    
731              switch (file->type)              switch (file->type)
732                  {                  {
733                  case UF_FILE:                  case UF_FILE:
734                      {                      {
735                          FILE *stream = fopen (file->name, "wb");                          FILE *stream = fopen (name, "wb");
736    
737                          if (stream == NULL)                          if (stream == NULL)
738                              {                              {
# Line 703  uar_extract (struct uar_archive *uar, co Line 754  uar_extract (struct uar_archive *uar, co
754                      break;                      break;
755    
756                  case UF_DIR:                  case UF_DIR:
757                      if (mkdir (file->name, file->mode) != 0)                      if (file->namelen == 1
758                            && file->name[0] == UAR_ROOT_DIR_NAME)
759                            continue;
760    
761                        if (mkdir (name, file->mode) != 0)
762                          {                          {
763                              uar_set_error (uar, UAR_SYSTEM_ERROR);                              uar_set_error (uar, UAR_SYSTEM_ERROR);
764                              return false;                              return false;

Legend:
Removed from v.24  
changed lines
  Added in v.25

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26