PrintToVeraeTimeStamp/internal/netprint/service_log.go
Cursor Agent 1d8dbac81a
Advertise AirPrint subtypes and keep job folders, formats, and the service log consistent.
Windows DnsServiceRegister now registers the Bonjour service-type form and the RFC subtype name so a Mac browse of _ipp._tcp,_universal can see the printer. document-format-supported matches the TXT pdl list, including JPEG. Job ids persist in next-job and job-N directories. The service log is written and flushed even when stderr fails. The tray is started by Task Scheduler or Explorer so setup is not its parent.

Co-authored-by: George Lambert <marchon@gmail.com>
2026-10-04 22:16:54 +00:00

66 lines
1.6 KiB
Go

package netprint
import (
"io"
"log"
"os"
"path/filepath"
)
// serviceLogWriter appends each line to the log file and flushes it.
// A Windows service has no console, so os.Stderr.Write fails. io.MultiWriter
// stops at that first error and never reaches the file, which left
// netprint.log at 0 bytes. The file is written first; stderr is best-effort.
type serviceLogWriter struct {
file *os.File
extra io.Writer
}
func (w *serviceLogWriter) Write(p []byte) (int, error) {
if w == nil || w.file == nil {
return 0, os.ErrInvalid
}
n, err := w.file.Write(p)
if err != nil {
return n, err
}
if n != len(p) {
return n, io.ErrShortWrite
}
_ = w.file.Sync()
if w.extra != nil {
_, _ = w.extra.Write(p)
}
return n, nil
}
// setupServiceLog appends the service log under %ProgramData%\Verae\logs on Windows.
// VERAE_LOG_DIR overrides the directory (used by tests).
func setupServiceLog() {
dir := serviceLogDir()
if err := os.MkdirAll(dir, 0o755); err != nil {
log.Printf("netprint: log directory: %v", err)
return
}
_ = osChmodUsers(dir)
f, err := os.OpenFile(filepath.Join(dir, "netprint.log"), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
if err != nil {
log.Printf("netprint: log file: %v", err)
return
}
log.SetFlags(log.Ldate | log.Ltime)
log.SetOutput(&serviceLogWriter{file: f, extra: os.Stderr})
log.Printf("netprint: log file %s", f.Name())
}
func serviceLogDir() string {
if d := os.Getenv("VERAE_LOG_DIR"); d != "" {
return d
}
return defaultServiceLogDir()
}
func osChmodUsers(dir string) error {
// Users (S-1-5-32-545) can read the service log. Ignore failure when not elevated.
return execGrantUsers(dir)
}