+struct odes *
+task_status_find_part(struct odes *to, byte *part, uns create)
+{
+ for (struct oattr *a = obj_find_attr(to, 'P' + OBJ_ATTR_SON); a; a=a->same)
+ {
+ struct odes *o = a->son;
+ byte *name = obj_find_aval(o, 'P');
+ ASSERT(name);
+ if (!strcmp(name, part))
+ return o;
+ }
+ if (!create)
+ return NULL;
+ struct odes *o = obj_add_son(to, 'P' + OBJ_ATTR_SON);
+ obj_set_attr(o, 'P', part);
+ return o;
+}
+
+void task_submit_part(byte *user, byte *task, byte *part, byte *ext, uns version UNUSED, struct fastbuf *fb)
+{
+ byte *dir = stk_printf("solutions/%s/%s", user, task);
+ byte *name = stk_printf("%s/%s.%s", dir, part, ext);
+
+ struct stat st;
+ if (stat(dir, &st) < 0 && errno == ENOENT && mkdir(dir, 0777) < 0)
+ die("Cannot create %s: %m", dir);
+
+ bconfig(fb, BCONFIG_IS_TEMP_FILE, 0);
+ if (rename(fb->name, name) < 0)
+ die("Cannot rename %s to %s: %m", fb->name, name);
+}
+
+void task_delete_part(byte *user, byte *task, byte *part, byte *ext, uns version UNUSED)