00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00039 #include "tmpfs.h"
00040 #include "../../vfs/vfs.h"
00041 #include <errno.h>
00042 #include <stdlib.h>
00043 #include <str.h>
00044 #include <sys/types.h>
00045 #include <as.h>
00046 #include <libblock.h>
00047 #include <byteorder.h>
00048
00049 #define TMPFS_COMM_SIZE 1024
00050
00051 struct rdentry {
00052 uint8_t type;
00053 uint32_t len;
00054 } __attribute__((packed));
00055
00056 static bool
00057 tmpfs_restore_recursion(devmap_handle_t dev, size_t *bufpos, size_t *buflen,
00058 aoff64_t *pos, fs_node_t *pfn)
00059 {
00060 struct rdentry entry;
00061 libfs_ops_t *ops = &tmpfs_libfs_ops;
00062 int rc;
00063
00064 do {
00065 char *fname;
00066 fs_node_t *fn;
00067 tmpfs_node_t *nodep;
00068 uint32_t size;
00069
00070 if (block_seqread(dev, bufpos, buflen, pos, &entry,
00071 sizeof(entry)) != EOK)
00072 return false;
00073
00074 entry.len = uint32_t_le2host(entry.len);
00075
00076 switch (entry.type) {
00077 case TMPFS_NONE:
00078 break;
00079 case TMPFS_FILE:
00080 fname = malloc(entry.len + 1);
00081 if (fname == NULL)
00082 return false;
00083
00084 rc = ops->create(&fn, dev, L_FILE);
00085 if (rc != EOK || fn == NULL) {
00086 free(fname);
00087 return false;
00088 }
00089
00090 if (block_seqread(dev, bufpos, buflen, pos, fname,
00091 entry.len) != EOK) {
00092 (void) ops->destroy(fn);
00093 free(fname);
00094 return false;
00095 }
00096 fname[entry.len] = 0;
00097
00098 rc = ops->link(pfn, fn, fname);
00099 if (rc != EOK) {
00100 (void) ops->destroy(fn);
00101 free(fname);
00102 return false;
00103 }
00104 free(fname);
00105
00106 if (block_seqread(dev, bufpos, buflen, pos, &size,
00107 sizeof(size)) != EOK)
00108 return false;
00109
00110 size = uint32_t_le2host(size);
00111
00112 nodep = TMPFS_NODE(fn);
00113 nodep->data = malloc(size);
00114 if (nodep->data == NULL)
00115 return false;
00116
00117 nodep->size = size;
00118 if (block_seqread(dev, bufpos, buflen, pos, nodep->data,
00119 size) != EOK)
00120 return false;
00121
00122 break;
00123 case TMPFS_DIRECTORY:
00124 fname = malloc(entry.len + 1);
00125 if (fname == NULL)
00126 return false;
00127
00128 rc = ops->create(&fn, dev, L_DIRECTORY);
00129 if (rc != EOK || fn == NULL) {
00130 free(fname);
00131 return false;
00132 }
00133
00134 if (block_seqread(dev, bufpos, buflen, pos, fname,
00135 entry.len) != EOK) {
00136 (void) ops->destroy(fn);
00137 free(fname);
00138 return false;
00139 }
00140 fname[entry.len] = 0;
00141
00142 rc = ops->link(pfn, fn, fname);
00143 if (rc != EOK) {
00144 (void) ops->destroy(fn);
00145 free(fname);
00146 return false;
00147 }
00148 free(fname);
00149
00150 if (!tmpfs_restore_recursion(dev, bufpos, buflen, pos,
00151 fn))
00152 return false;
00153
00154 break;
00155 default:
00156 return false;
00157 }
00158 } while (entry.type != TMPFS_NONE);
00159
00160 return true;
00161 }
00162
00163 bool tmpfs_restore(devmap_handle_t dev)
00164 {
00165 libfs_ops_t *ops = &tmpfs_libfs_ops;
00166 fs_node_t *fn;
00167 int rc;
00168
00169 rc = block_init(dev, TMPFS_COMM_SIZE);
00170 if (rc != EOK)
00171 return false;
00172
00173 size_t bufpos = 0;
00174 size_t buflen = 0;
00175 aoff64_t pos = 0;
00176
00177 char tag[6];
00178 if (block_seqread(dev, &bufpos, &buflen, &pos, tag, 5) != EOK)
00179 goto error;
00180
00181 tag[5] = 0;
00182 if (str_cmp(tag, "TMPFS") != 0)
00183 goto error;
00184
00185 rc = ops->root_get(&fn, dev);
00186 if (rc != EOK)
00187 goto error;
00188
00189 if (!tmpfs_restore_recursion(dev, &bufpos, &buflen, &pos, fn))
00190 goto error;
00191
00192 block_fini(dev);
00193 return true;
00194
00195 error:
00196 block_fini(dev);
00197 return false;
00198 }
00199