static ssize_t queue_var_store64(s64 *var, const char *page) { int err; s64 v; err = kstrtos64(page, 10, &v); if (err < 0) return err; *var = v; return 0; }
static ssize_t wakealarm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) { ssize_t retval; time64_t now, alarm; time64_t push = 0; struct rtc_wkalrm alm; struct rtc_device *rtc = to_rtc_device(dev); const char *buf_ptr; int adjust = 0; /* Only request alarms that trigger in the future. Disable them * by writing another time, e.g. 0 meaning Jan 1 1970 UTC. */ retval = rtc_read_time(rtc, &alm.time); if (retval < 0) return retval; now = rtc_tm_to_time64(&alm.time); buf_ptr = buf; if (*buf_ptr == '+') { buf_ptr++; if (*buf_ptr == '=') { buf_ptr++; push = 1; } else adjust = 1; } retval = kstrtos64(buf_ptr, 0, &alarm); if (retval) return retval; if (adjust) { alarm += now; } if (alarm > now || push) { /* Avoid accidentally clobbering active alarms; we can't * entirely prevent that here, without even the minimal * locking from the /dev/rtcN api. */ retval = rtc_read_alarm(rtc, &alm); if (retval < 0) return retval; if (alm.enabled) { if (push) { push = rtc_tm_to_time64(&alm.time); alarm += push; } else return -EBUSY; } else if (push) return -EINVAL; alm.enabled = 1; } else { alm.enabled = 0; /* Provide a valid future alarm time. Linux isn't EFI, * this time won't be ignored when disabling the alarm. */ alarm = now + 300; } rtc_time64_to_tm(alarm, &alm.time); retval = rtc_set_alarm(rtc, &alm); return (retval < 0) ? retval : n; }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DtaIoConfigParseIniFile -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. // static void DtaIoConfigParseIniFile( DtIoConfigValueDriver* pCfgValues, char* FileBuf, char* FileEnd) { Int ConfigCode = -1; char* p = FileBuf; while (p < FileEnd) { // We parse per line, so find where the current line ends char* pLineEnd = p; while (pLineEnd<FileEnd && *pLineEnd!='\n' && *pLineEnd!='\r') pLineEnd++; *pLineEnd = '\0'; while (p<pLineEnd && (*p==' ' || *p=='\t')) p++; if (*p==';' || *p=='#') { // Rest of the line is a comment, ignore it } else if (p == pLineEnd) { // Empty line, skip } else if (*p == '[') { // Start of new section char* pEndSectName; // Skip [ character p++; // Skip whitespace. Range check not needed since we have a terminating '\0' // at the end of the line. while (*p==' ' || *p=='\t') p++; pEndSectName = p; while (*pEndSectName!='\0' && *pEndSectName!=']') pEndSectName++; if (*pEndSectName != ']') { DtDbgOut(ERR, IOCONFIG, "Invalid section header"); return; } // Go backwards to last non-whitespace character // Cannot go out of bounds since it'll find the opening [ eventually if // nothing else. while (pEndSectName[-1]==' ' || pEndSectName[-1]=='\t') pEndSectName--; *pEndSectName = '\0'; if (!DT_SUCCESS(IoConfigCodeGet(p, &ConfigCode))) { DtDbgOut(ERR, IOCONFIG, "Unrecognized IoConfig category"); return; } } else { // Assume a key=value pair on this line char* pEq; char* pVal; char* pValEnd; if (ConfigCode == -1) { DtDbgOut(ERR, IOCONFIG, "key=value pair before first section"); return; } if (*p == '=') { // Line starts with = sign DtDbgOut(ERR, IOCONFIG, "Invalid line: not allowed to start with ="); return; } // Find equals sign pEq = p; while (pEq<pLineEnd && *pEq!='=') pEq++; if (pEq == pLineEnd) { DtDbgOut(ERR, IOCONFIG, "No = found"); return; } pVal = pEq+1; // Search backspace for last whitespace. We're guaranteed to find something, // first non-whitespace was not '='. while (pEq[-1]==' ' || pEq[-1]=='\t') pEq--; *pEq = '\0'; while (*pVal==' ' || *pVal=='\t') pVal++; // Find next whitespace or end-of-line. pValEnd = pVal; while (*pValEnd!=' ' && *pValEnd!='\t' && *pValEnd!='\0') pValEnd++; *pValEnd = '\0'; if (strcmp(p, "ConfigValue") == 0) { if (!DT_SUCCESS(IoConfigCodeGet(pVal, &pCfgValues[ConfigCode].m_Value))) { DtDbgOut(ERR, IOCONFIG, "Failed to parse ConfigValue"); return; } } else if (strcmp(p, "ConfigSubValue") == 0) { if (!DT_SUCCESS(IoConfigCodeGet(pVal,&pCfgValues[ConfigCode].m_SubValue))) { DtDbgOut(ERR, IOCONFIG, "Failed to parse ConfigSubValue"); return; } } else if (strcmp(p, "IoParXtra0") == 0) { if (kstrtos64(pVal, 0, &pCfgValues[ConfigCode].m_ParXtra[0]) < 0) { DtDbgOut(ERR, IOCONFIG, "Failed to parse IoParXtra0"); return; } } else if (strcmp(p, "IoParXtra1") == 0) { if (kstrtos64(pVal, 0, &pCfgValues[ConfigCode].m_ParXtra[1]) < 0) { DtDbgOut(ERR, IOCONFIG, "Failed to parse IoParXtra1"); return; } } else if (strcmp(p, "IoParXtra2") == 0) { if (kstrtos64(pVal, 0, &pCfgValues[ConfigCode].m_ParXtra[2]) < 0) { DtDbgOut(ERR, IOCONFIG, "Failed to parse IoParXtra2"); return; } } else if (strcmp(p, "IoParXtra3") == 0) { if (kstrtos64(pVal, 0, &pCfgValues[ConfigCode].m_ParXtra[3]) < 0) { DtDbgOut(ERR, IOCONFIG, "Failed to parse IoParXtra3"); return; } } else { DtDbgOut(ERR, IOCONFIG, "Unknown key encountered"); return; } } p = pLineEnd+1; } }