package api import ( "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "path/filepath" "syscall" "up/utils" ) func ExtlinuxWrite(w http.ResponseWriter, r *http.Request) { var MOUNT_POINT = os.Getenv("MOUNT_POINT") var EXTLINUX_FILE = os.Getenv("EXTLINUX_FILE") // Ограничиваем размер тела, чтобы избежать слишком больших запросов (аналог 4096 в C) r.Body = http.MaxBytesReader(w, r.Body, 4096) body, err := io.ReadAll(r.Body) if err != nil { http.Error(w, `{"error":"Failed to read body"}`, http.StatusBadRequest) return } // Парсим JSON var requestData struct { Content string `json:"content"` } if err := json.Unmarshal(body, &requestData); err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) w.Write([]byte(`{"error":"Invalid JSON"}`)) return } // Проверяем наличие поля content if requestData.Content == "" { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusBadRequest) w.Write([]byte(`{"error":"Missing content field"}`)) return } timestamp := r.URL.Query().Get("timestamp") if timestamp != "" { // Полное URL-декодирование (в C декодировался только %3A, но здесь используем стандартный способ) decoded, err := url.QueryUnescape(timestamp) if err == nil { timestamp = decoded } } // Монтируем устройство if utils.MountDevice() < 0 { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(`{"error":"Failed to mount device"}`)) return } // Формируем полный путь к файлу filePath := filepath.Join(MOUNT_POINT, EXTLINUX_FILE) fmt.Println(filePath) // Открываем файл на запись (создаём/перезаписываем) f, err := os.Create(filePath) if err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(`{"error":"Failed to open file"}`)) return } defer f.Close() // Записываем содержимое if _, err := f.WriteString(requestData.Content); err != nil { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(`{"error":"Failed to write file"}`)) return } if timestamp != "" { versionPath := filepath.Join(MOUNT_POINT, EXTLINUX_FILE+".version") vf, err := os.Create(versionPath) if err == nil { // Форматируем ISO 8601 в человекочитаемый вид (как в C) var readableDate string if len(timestamp) >= 19 { readableDate = timestamp[:10] + " " + timestamp[11:19] // "YYYY-MM-DD HH:MM:SS" } else { readableDate = timestamp } vf.WriteString(readableDate + "\n") vf.Close() log.Printf("Written extlinux.conf version: %s\n", readableDate) } } // Принудительно сбрасываем файловые буферы на диск (аналог sync()) syscall.Sync() // Успешный ответ w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) w.Write([]byte(`{"status":"success","message":"extlinux.conf updated"}`)) }